@objectstack/service-sms 17.2.0 → 17.4.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.
- package/CHANGELOG.md +515 -0
- package/dist/index.d.mts +14 -7
- package/dist/index.d.ts +14 -7
- package/dist/index.js +19 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +19 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,520 @@
|
|
|
1
1
|
# @objectstack/service-sms
|
|
2
2
|
|
|
3
|
+
## 17.4.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- be92d46: These fourteen packages now declare `repository.directory`, so their npm pages carry a working "source" deep link to their own directory in the monorepo.
|
|
8
|
+
|
|
9
|
+
npm renders that field by concatenating it onto `repository.url`. None of these fourteen manifests carried a `repository` block at all, so every one of their npm pages offered no route from the package back to its code — not a broken link, no link. That is what this publishes: the block those pages read, naming each package's own directory.
|
|
10
|
+
|
|
11
|
+
Nothing else about these packages changes. No export, no runtime behaviour, no dependency and no file in the tarball other than the manifest's own `repository` key. The version bump exists because the fix is only real once it is published: the field lives in the manifest npm serves, so a corrected manifest sitting in the repository leaves the package page exactly as wrong as it was.
|
|
12
|
+
|
|
13
|
+
The rule behind it is now mechanical rather than remembered — `check:manifest-repository-directory` makes a publishable (non-private) workspace manifest declare the field naming its own directory, so a package added or moved after this cannot quietly go back to having no source link.
|
|
14
|
+
- Updated dependencies [fe0d9a4]
|
|
15
|
+
- Updated dependencies [ecd2158]
|
|
16
|
+
- Updated dependencies [f2b5e46]
|
|
17
|
+
- Updated dependencies [2ed6be6]
|
|
18
|
+
- Updated dependencies [ed7243d]
|
|
19
|
+
- Updated dependencies [6ba0db4]
|
|
20
|
+
- Updated dependencies [625b0c3]
|
|
21
|
+
- Updated dependencies [233222e]
|
|
22
|
+
- Updated dependencies [07f40e5]
|
|
23
|
+
- Updated dependencies [ceb4877]
|
|
24
|
+
- Updated dependencies [e9fcd6b]
|
|
25
|
+
- Updated dependencies [90e7e6d]
|
|
26
|
+
- Updated dependencies [2bdabe6]
|
|
27
|
+
- Updated dependencies [ca326b5]
|
|
28
|
+
- Updated dependencies [8f404a5]
|
|
29
|
+
- Updated dependencies [d4c2cb1]
|
|
30
|
+
- Updated dependencies [68437d4]
|
|
31
|
+
- Updated dependencies [abb140c]
|
|
32
|
+
- Updated dependencies [2e6a2ea]
|
|
33
|
+
- Updated dependencies [8333a6c]
|
|
34
|
+
- Updated dependencies [3e3ecb0]
|
|
35
|
+
- Updated dependencies [3030369]
|
|
36
|
+
- Updated dependencies [8e500f2]
|
|
37
|
+
- Updated dependencies [d5d8d50]
|
|
38
|
+
- Updated dependencies [e08892d]
|
|
39
|
+
- Updated dependencies [ae05f2e]
|
|
40
|
+
- Updated dependencies [b548e43]
|
|
41
|
+
- Updated dependencies [c463d03]
|
|
42
|
+
- Updated dependencies [64bd6a3]
|
|
43
|
+
- Updated dependencies [13c48c2]
|
|
44
|
+
- Updated dependencies [b0529e1]
|
|
45
|
+
- Updated dependencies [66dc6ab]
|
|
46
|
+
- Updated dependencies [6f94458]
|
|
47
|
+
- Updated dependencies [6e67b86]
|
|
48
|
+
- Updated dependencies [132742f]
|
|
49
|
+
- Updated dependencies [85a2459]
|
|
50
|
+
- Updated dependencies [50dc214]
|
|
51
|
+
- Updated dependencies [e89fa92]
|
|
52
|
+
- Updated dependencies [e9fcd6b]
|
|
53
|
+
- Updated dependencies [8976ea1]
|
|
54
|
+
- Updated dependencies [56fe8c2]
|
|
55
|
+
- Updated dependencies [acabd24]
|
|
56
|
+
- Updated dependencies [ab50c8f]
|
|
57
|
+
- Updated dependencies [6491463]
|
|
58
|
+
- Updated dependencies [89cf4d6]
|
|
59
|
+
- Updated dependencies [21c5dcb]
|
|
60
|
+
- Updated dependencies [6d4d5d3]
|
|
61
|
+
- Updated dependencies [ed5d557]
|
|
62
|
+
- Updated dependencies [bca21f7]
|
|
63
|
+
- Updated dependencies [e9fcd6b]
|
|
64
|
+
- Updated dependencies [2025b1f]
|
|
65
|
+
- Updated dependencies [1a7a7c9]
|
|
66
|
+
- Updated dependencies [e9fcd6b]
|
|
67
|
+
- Updated dependencies [ef3a138]
|
|
68
|
+
- Updated dependencies [68d5dfd]
|
|
69
|
+
- Updated dependencies [3e21cf0]
|
|
70
|
+
- Updated dependencies [4cfc93b]
|
|
71
|
+
- Updated dependencies [efd6b43]
|
|
72
|
+
- Updated dependencies [859ded3]
|
|
73
|
+
- Updated dependencies [fa125f3]
|
|
74
|
+
- Updated dependencies [74628d9]
|
|
75
|
+
- Updated dependencies [a646120]
|
|
76
|
+
- Updated dependencies [6f1ce7d]
|
|
77
|
+
- Updated dependencies [7778115]
|
|
78
|
+
- Updated dependencies [2c753fe]
|
|
79
|
+
- Updated dependencies [52804cd]
|
|
80
|
+
- Updated dependencies [3f89967]
|
|
81
|
+
- Updated dependencies [53cf263]
|
|
82
|
+
- Updated dependencies [21aabbc]
|
|
83
|
+
- Updated dependencies [9c270bb]
|
|
84
|
+
- Updated dependencies [76c8c5a]
|
|
85
|
+
- Updated dependencies [cfb64a6]
|
|
86
|
+
- Updated dependencies [a84e1ce]
|
|
87
|
+
- Updated dependencies [bf1054a]
|
|
88
|
+
- Updated dependencies [d8d2776]
|
|
89
|
+
- Updated dependencies [222dc0f]
|
|
90
|
+
- Updated dependencies [e9fcd6b]
|
|
91
|
+
- Updated dependencies [32c917d]
|
|
92
|
+
- Updated dependencies [f9a3c32]
|
|
93
|
+
- Updated dependencies [41cbc54]
|
|
94
|
+
- Updated dependencies [f502898]
|
|
95
|
+
- Updated dependencies [51ae731]
|
|
96
|
+
- Updated dependencies [af7edfe]
|
|
97
|
+
- Updated dependencies [9f39897]
|
|
98
|
+
- Updated dependencies [b60f48b]
|
|
99
|
+
- Updated dependencies [c78c918]
|
|
100
|
+
- Updated dependencies [142c01c]
|
|
101
|
+
- Updated dependencies [4ca358d]
|
|
102
|
+
- Updated dependencies [cf9bda4]
|
|
103
|
+
- Updated dependencies [784cb92]
|
|
104
|
+
- Updated dependencies [7629f4d]
|
|
105
|
+
- Updated dependencies [51df9fd]
|
|
106
|
+
- Updated dependencies [a7da4de]
|
|
107
|
+
- Updated dependencies [de0bcdd]
|
|
108
|
+
- Updated dependencies [70f7d6d]
|
|
109
|
+
- Updated dependencies [c677cda]
|
|
110
|
+
- Updated dependencies [6acb37e]
|
|
111
|
+
- Updated dependencies [554a160]
|
|
112
|
+
- Updated dependencies [f7da71e]
|
|
113
|
+
- Updated dependencies [7f745c3]
|
|
114
|
+
- Updated dependencies [9e9f03a]
|
|
115
|
+
- Updated dependencies [5eb24f8]
|
|
116
|
+
- Updated dependencies [2a3decc]
|
|
117
|
+
- Updated dependencies [cc00df2]
|
|
118
|
+
- Updated dependencies [cc00df2]
|
|
119
|
+
- Updated dependencies [f4e6adf]
|
|
120
|
+
- Updated dependencies [ee4a59b]
|
|
121
|
+
- Updated dependencies [4db3c61]
|
|
122
|
+
- Updated dependencies [5ca314a]
|
|
123
|
+
- Updated dependencies [e0af1a8]
|
|
124
|
+
- Updated dependencies [4771bd9]
|
|
125
|
+
- Updated dependencies [414c1fc]
|
|
126
|
+
- Updated dependencies [22c0279]
|
|
127
|
+
- Updated dependencies [0db2947]
|
|
128
|
+
- Updated dependencies [92b5d7f]
|
|
129
|
+
- Updated dependencies [613bfbd]
|
|
130
|
+
- Updated dependencies [abae16a]
|
|
131
|
+
- Updated dependencies [094b8fd]
|
|
132
|
+
- Updated dependencies [c7aca0d]
|
|
133
|
+
- Updated dependencies [c1d8f98]
|
|
134
|
+
- Updated dependencies [8e0b297]
|
|
135
|
+
- Updated dependencies [d4f9b2a]
|
|
136
|
+
- Updated dependencies [5f7fa1d]
|
|
137
|
+
- Updated dependencies [87f0ccc]
|
|
138
|
+
- Updated dependencies [aedbaef]
|
|
139
|
+
- Updated dependencies [a727043]
|
|
140
|
+
- Updated dependencies [c5d6803]
|
|
141
|
+
- Updated dependencies [10d05bb]
|
|
142
|
+
- Updated dependencies [69602e5]
|
|
143
|
+
- Updated dependencies [c3ce76c]
|
|
144
|
+
- Updated dependencies [7936b29]
|
|
145
|
+
- Updated dependencies [46803fa]
|
|
146
|
+
- Updated dependencies [c2a336c]
|
|
147
|
+
- Updated dependencies [9f890d3]
|
|
148
|
+
- Updated dependencies [0bb2318]
|
|
149
|
+
- Updated dependencies [f7db8f4]
|
|
150
|
+
- Updated dependencies [1ecee3e]
|
|
151
|
+
- Updated dependencies [9408b7f]
|
|
152
|
+
- Updated dependencies [e9fcd6b]
|
|
153
|
+
- Updated dependencies [9bcd9be]
|
|
154
|
+
- Updated dependencies [b398ad2]
|
|
155
|
+
- Updated dependencies [99261a7]
|
|
156
|
+
- Updated dependencies [81b426f]
|
|
157
|
+
- Updated dependencies [001af1c]
|
|
158
|
+
- Updated dependencies [fb77aa5]
|
|
159
|
+
- Updated dependencies [581d8f8]
|
|
160
|
+
- Updated dependencies [f81afe3]
|
|
161
|
+
- Updated dependencies [40a44b9]
|
|
162
|
+
- Updated dependencies [f89812e]
|
|
163
|
+
- Updated dependencies [7a7fb03]
|
|
164
|
+
- Updated dependencies [8fd246d]
|
|
165
|
+
- @objectstack/spec@17.4.0
|
|
166
|
+
- @objectstack/core@17.4.0
|
|
167
|
+
- @objectstack/plugin-auth@17.4.0
|
|
168
|
+
|
|
169
|
+
## 17.3.0
|
|
170
|
+
|
|
171
|
+
### Patch Changes
|
|
172
|
+
|
|
173
|
+
- 6426b86: fix(service-storage,service-sms): a schema default is not a configuration — converge the "authored value" criterion on `ResolvedSettingValue.source` (#5536)
|
|
174
|
+
|
|
175
|
+
Both settings-bound plugins decided "has anyone configured this namespace?" by
|
|
176
|
+
value presence, but the manifest defaults are non-empty on every boot, so an
|
|
177
|
+
unopened settings page read as configuration:
|
|
178
|
+
|
|
179
|
+
- **service-storage**: the swap gate now requires an adapter-relevant key
|
|
180
|
+
(`adapter`, `local_root`, `s3_*` — exactly the inputs `resolveStorageTarget`
|
|
181
|
+
reads) whose `source` is not `'default'` before settings may override the
|
|
182
|
+
constructor-built adapter. Previously the schema defaults
|
|
183
|
+
(`adapter: 'local'`, `local_root: './.objectstack/data/uploads'`) could
|
|
184
|
+
silently move a deployment's declared backing store — and an authored save
|
|
185
|
+
that touched only, say, the upload limit could open the same door.
|
|
186
|
+
- **service-sms**: the downgrade to `LogSmsTransport` now requires an
|
|
187
|
+
operator-authored `provider: 'log'` (`source !== 'default'`). Previously
|
|
188
|
+
the manifest default `'log'` — a value nobody selected — switched off the
|
|
189
|
+
transport the deployment declared via constructor options on every boot.
|
|
190
|
+
|
|
191
|
+
Same criterion, same reason as `EmailServicePlugin` (the in-repo precedent):
|
|
192
|
+
the manifest default (`source: 'default'`) is not a decision anyone made.
|
|
193
|
+
Admin-saved rows and env overrides behave exactly as before. A snapshot with
|
|
194
|
+
no `source` at all reads as `'default'` — the conservative side keeps the
|
|
195
|
+
deployment-declared adapter/transport. The sms `daily_quota` reader keeps its
|
|
196
|
+
declared #2814 exception and still binds by value, never by source.
|
|
197
|
+
- Updated dependencies [809d417]
|
|
198
|
+
- Updated dependencies [387e231]
|
|
199
|
+
- Updated dependencies [f794e4e]
|
|
200
|
+
- Updated dependencies [cae2169]
|
|
201
|
+
- Updated dependencies [b812a54]
|
|
202
|
+
- Updated dependencies [2d4fa75]
|
|
203
|
+
- Updated dependencies [0e4e51b]
|
|
204
|
+
- Updated dependencies [e84bbf6]
|
|
205
|
+
- Updated dependencies [effae80]
|
|
206
|
+
- Updated dependencies [efb3513]
|
|
207
|
+
- Updated dependencies [d62f990]
|
|
208
|
+
- Updated dependencies [c45d8e6]
|
|
209
|
+
- Updated dependencies [8064e6d]
|
|
210
|
+
- Updated dependencies [6dd3e69]
|
|
211
|
+
- Updated dependencies [2e3e8c7]
|
|
212
|
+
- Updated dependencies [e621291]
|
|
213
|
+
- Updated dependencies [655b106]
|
|
214
|
+
- Updated dependencies [40a93b5]
|
|
215
|
+
- Updated dependencies [d5b330d]
|
|
216
|
+
- Updated dependencies [dda969c]
|
|
217
|
+
- Updated dependencies [1f45690]
|
|
218
|
+
- Updated dependencies [277948f]
|
|
219
|
+
- Updated dependencies [8bdd955]
|
|
220
|
+
- Updated dependencies [f3bbbef]
|
|
221
|
+
- Updated dependencies [4f24e9d]
|
|
222
|
+
- Updated dependencies [e238c79]
|
|
223
|
+
- Updated dependencies [8e31083]
|
|
224
|
+
- Updated dependencies [cd288b4]
|
|
225
|
+
- Updated dependencies [4bb412b]
|
|
226
|
+
- Updated dependencies [a5b95ee]
|
|
227
|
+
- Updated dependencies [450e73b]
|
|
228
|
+
- Updated dependencies [2efa1e1]
|
|
229
|
+
- Updated dependencies [35e94c9]
|
|
230
|
+
- Updated dependencies [3798424]
|
|
231
|
+
- Updated dependencies [e27583e]
|
|
232
|
+
- Updated dependencies [4bd6faa]
|
|
233
|
+
- Updated dependencies [86cbe37]
|
|
234
|
+
- Updated dependencies [6a180e4]
|
|
235
|
+
- Updated dependencies [474242f]
|
|
236
|
+
- Updated dependencies [63cd487]
|
|
237
|
+
- Updated dependencies [bd4aa4e]
|
|
238
|
+
- Updated dependencies [803eaab]
|
|
239
|
+
- Updated dependencies [f8e8f03]
|
|
240
|
+
- Updated dependencies [983edf1]
|
|
241
|
+
- Updated dependencies [eae824e]
|
|
242
|
+
- Updated dependencies [9c4c431]
|
|
243
|
+
- Updated dependencies [f6fa22c]
|
|
244
|
+
- Updated dependencies [56d3c7a]
|
|
245
|
+
- Updated dependencies [8a483b3]
|
|
246
|
+
- Updated dependencies [97bcd99]
|
|
247
|
+
- Updated dependencies [df59de0]
|
|
248
|
+
- Updated dependencies [96e25a8]
|
|
249
|
+
- Updated dependencies [f75a38a]
|
|
250
|
+
- Updated dependencies [7a25e7d]
|
|
251
|
+
- Updated dependencies [d3bee87]
|
|
252
|
+
- Updated dependencies [1fa05a6]
|
|
253
|
+
- Updated dependencies [c85a265]
|
|
254
|
+
- Updated dependencies [dcb10a5]
|
|
255
|
+
- Updated dependencies [773a999]
|
|
256
|
+
- Updated dependencies [35dffea]
|
|
257
|
+
- Updated dependencies [d8024f0]
|
|
258
|
+
- Updated dependencies [8120808]
|
|
259
|
+
- Updated dependencies [776a098]
|
|
260
|
+
- Updated dependencies [5060877]
|
|
261
|
+
- Updated dependencies [4f6325d]
|
|
262
|
+
- Updated dependencies [52954c0]
|
|
263
|
+
- Updated dependencies [2aa8456]
|
|
264
|
+
- Updated dependencies [93809a3]
|
|
265
|
+
- Updated dependencies [7c0d0c3]
|
|
266
|
+
- Updated dependencies [daae7aa]
|
|
267
|
+
- Updated dependencies [8dc22d6]
|
|
268
|
+
- Updated dependencies [279431e]
|
|
269
|
+
- Updated dependencies [948dd6b]
|
|
270
|
+
- Updated dependencies [3b4c56c]
|
|
271
|
+
- Updated dependencies [ae8edd2]
|
|
272
|
+
- Updated dependencies [e25403c]
|
|
273
|
+
- Updated dependencies [5c9e40a]
|
|
274
|
+
- Updated dependencies [64baa68]
|
|
275
|
+
- Updated dependencies [9fa70d7]
|
|
276
|
+
- Updated dependencies [09db64a]
|
|
277
|
+
- Updated dependencies [92916e7]
|
|
278
|
+
- Updated dependencies [a84f3ea]
|
|
279
|
+
- Updated dependencies [f2eaae8]
|
|
280
|
+
- Updated dependencies [c09451b]
|
|
281
|
+
- Updated dependencies [ba64877]
|
|
282
|
+
- Updated dependencies [35202f1]
|
|
283
|
+
- Updated dependencies [7345308]
|
|
284
|
+
- Updated dependencies [79b6a22]
|
|
285
|
+
- Updated dependencies [30d96ab]
|
|
286
|
+
- Updated dependencies [f658793]
|
|
287
|
+
- Updated dependencies [c95ad19]
|
|
288
|
+
- Updated dependencies [e58ea8b]
|
|
289
|
+
- Updated dependencies [4a17645]
|
|
290
|
+
- Updated dependencies [3795c5f]
|
|
291
|
+
- Updated dependencies [8ab926b]
|
|
292
|
+
- Updated dependencies [7317cf2]
|
|
293
|
+
- Updated dependencies [e25e839]
|
|
294
|
+
- Updated dependencies [5997207]
|
|
295
|
+
- Updated dependencies [8b13cc8]
|
|
296
|
+
- Updated dependencies [4a4a35d]
|
|
297
|
+
- Updated dependencies [86e765a]
|
|
298
|
+
- Updated dependencies [1d7e76a]
|
|
299
|
+
- Updated dependencies [53dc739]
|
|
300
|
+
- Updated dependencies [fd289be]
|
|
301
|
+
- Updated dependencies [03bf7b1]
|
|
302
|
+
- Updated dependencies [f90e820]
|
|
303
|
+
- Updated dependencies [18d816a]
|
|
304
|
+
- Updated dependencies [e8bd715]
|
|
305
|
+
- Updated dependencies [b91c351]
|
|
306
|
+
- Updated dependencies [a28a3c0]
|
|
307
|
+
- Updated dependencies [daeaaf9]
|
|
308
|
+
- Updated dependencies [c459da6]
|
|
309
|
+
- Updated dependencies [e914733]
|
|
310
|
+
- Updated dependencies [f887e52]
|
|
311
|
+
- Updated dependencies [881f8d8]
|
|
312
|
+
- Updated dependencies [3bfa1e6]
|
|
313
|
+
- Updated dependencies [0a8ebf3]
|
|
314
|
+
- Updated dependencies [901355c]
|
|
315
|
+
- Updated dependencies [34ce8e7]
|
|
316
|
+
- Updated dependencies [33681ea]
|
|
317
|
+
- Updated dependencies [4635f3e]
|
|
318
|
+
- Updated dependencies [fd289be]
|
|
319
|
+
- Updated dependencies [ee3595c]
|
|
320
|
+
- Updated dependencies [b2eab95]
|
|
321
|
+
- Updated dependencies [93940d4]
|
|
322
|
+
- Updated dependencies [3a04b01]
|
|
323
|
+
- Updated dependencies [45b9051]
|
|
324
|
+
- Updated dependencies [b9e9227]
|
|
325
|
+
- Updated dependencies [d395692]
|
|
326
|
+
- Updated dependencies [f074616]
|
|
327
|
+
- Updated dependencies [0e0bf80]
|
|
328
|
+
- Updated dependencies [5894d30]
|
|
329
|
+
- Updated dependencies [a3765f6]
|
|
330
|
+
- Updated dependencies [2d5cee3]
|
|
331
|
+
- Updated dependencies [e22158f]
|
|
332
|
+
- Updated dependencies [7404925]
|
|
333
|
+
- Updated dependencies [0c2334f]
|
|
334
|
+
- Updated dependencies [778c59f]
|
|
335
|
+
- Updated dependencies [d2619fd]
|
|
336
|
+
- Updated dependencies [af56546]
|
|
337
|
+
- Updated dependencies [6acb11a]
|
|
338
|
+
- Updated dependencies [33c5fd3]
|
|
339
|
+
- Updated dependencies [20b0fdb]
|
|
340
|
+
- Updated dependencies [905019b]
|
|
341
|
+
- Updated dependencies [a286411]
|
|
342
|
+
- Updated dependencies [98c0d33]
|
|
343
|
+
- Updated dependencies [368a82e]
|
|
344
|
+
- Updated dependencies [a3d5724]
|
|
345
|
+
- Updated dependencies [93ea19b]
|
|
346
|
+
- Updated dependencies [9ee2dcf]
|
|
347
|
+
- Updated dependencies [8cb96ec]
|
|
348
|
+
- Updated dependencies [8f10a79]
|
|
349
|
+
- Updated dependencies [6269a55]
|
|
350
|
+
- Updated dependencies [a17da05]
|
|
351
|
+
- Updated dependencies [a8c00e2]
|
|
352
|
+
- Updated dependencies [0fb8760]
|
|
353
|
+
- Updated dependencies [e5ce2ed]
|
|
354
|
+
- Updated dependencies [be21955]
|
|
355
|
+
- Updated dependencies [bc56e18]
|
|
356
|
+
- Updated dependencies [be21955]
|
|
357
|
+
- Updated dependencies [a9ee989]
|
|
358
|
+
- Updated dependencies [4d0d944]
|
|
359
|
+
- Updated dependencies [15d58db]
|
|
360
|
+
- Updated dependencies [d63b014]
|
|
361
|
+
- Updated dependencies [9abe4e4]
|
|
362
|
+
- Updated dependencies [2cc7122]
|
|
363
|
+
- Updated dependencies [50d6c92]
|
|
364
|
+
- Updated dependencies [9e0ba21]
|
|
365
|
+
- Updated dependencies [311433f]
|
|
366
|
+
- Updated dependencies [3e5ad08]
|
|
367
|
+
- Updated dependencies [9abe4e4]
|
|
368
|
+
- Updated dependencies [b7131f3]
|
|
369
|
+
- Updated dependencies [e5812fa]
|
|
370
|
+
- Updated dependencies [7085f90]
|
|
371
|
+
- Updated dependencies [dee4dd4]
|
|
372
|
+
- Updated dependencies [ce7e497]
|
|
373
|
+
- Updated dependencies [51ecb2f]
|
|
374
|
+
- Updated dependencies [9086761]
|
|
375
|
+
- Updated dependencies [42a117b]
|
|
376
|
+
- Updated dependencies [1401ae7]
|
|
377
|
+
- Updated dependencies [4297fe7]
|
|
378
|
+
- Updated dependencies [e398863]
|
|
379
|
+
- Updated dependencies [d16df74]
|
|
380
|
+
- Updated dependencies [f11fc61]
|
|
381
|
+
- Updated dependencies [e808890]
|
|
382
|
+
- Updated dependencies [8f79379]
|
|
383
|
+
- Updated dependencies [e6ca40e]
|
|
384
|
+
- Updated dependencies [0c77ea4]
|
|
385
|
+
- Updated dependencies [52954c0]
|
|
386
|
+
- Updated dependencies [89eb997]
|
|
387
|
+
- Updated dependencies [7131f12]
|
|
388
|
+
- Updated dependencies [aa5994e]
|
|
389
|
+
- Updated dependencies [be93457]
|
|
390
|
+
- Updated dependencies [7c342f4]
|
|
391
|
+
- Updated dependencies [a65db76]
|
|
392
|
+
- Updated dependencies [2cf5a96]
|
|
393
|
+
- Updated dependencies [15eb2c9]
|
|
394
|
+
- Updated dependencies [5691b07]
|
|
395
|
+
- Updated dependencies [2a6122b]
|
|
396
|
+
- Updated dependencies [225e769]
|
|
397
|
+
- Updated dependencies [8af88dd]
|
|
398
|
+
- Updated dependencies [fb5fbb8]
|
|
399
|
+
- Updated dependencies [d7b3963]
|
|
400
|
+
- Updated dependencies [33184fd]
|
|
401
|
+
- Updated dependencies [7c41693]
|
|
402
|
+
- Updated dependencies [3c0f3ea]
|
|
403
|
+
- Updated dependencies [4f65837]
|
|
404
|
+
- Updated dependencies [26deb31]
|
|
405
|
+
- Updated dependencies [b72db01]
|
|
406
|
+
- Updated dependencies [dce5cd4]
|
|
407
|
+
- Updated dependencies [9688f58]
|
|
408
|
+
- Updated dependencies [556ebc1]
|
|
409
|
+
- Updated dependencies [177ebdc]
|
|
410
|
+
- Updated dependencies [ad54eb3]
|
|
411
|
+
- Updated dependencies [8d237b4]
|
|
412
|
+
- Updated dependencies [2d2e6f0]
|
|
413
|
+
- Updated dependencies [2d8dd8d]
|
|
414
|
+
- Updated dependencies [22d573e]
|
|
415
|
+
- Updated dependencies [b5a2398]
|
|
416
|
+
- Updated dependencies [348860c]
|
|
417
|
+
- Updated dependencies [5383fa6]
|
|
418
|
+
- Updated dependencies [5b3ff63]
|
|
419
|
+
- Updated dependencies [1a6a19c]
|
|
420
|
+
- Updated dependencies [527e050]
|
|
421
|
+
- Updated dependencies [dd33bf9]
|
|
422
|
+
- Updated dependencies [4cb2a90]
|
|
423
|
+
- Updated dependencies [74a7804]
|
|
424
|
+
- Updated dependencies [53d3689]
|
|
425
|
+
- Updated dependencies [b3a63d3]
|
|
426
|
+
- Updated dependencies [911da5f]
|
|
427
|
+
- Updated dependencies [89448a5]
|
|
428
|
+
- Updated dependencies [49f0dcf]
|
|
429
|
+
- Updated dependencies [033a34c]
|
|
430
|
+
- Updated dependencies [4d25d22]
|
|
431
|
+
- Updated dependencies [1ffee51]
|
|
432
|
+
- Updated dependencies [5ae4303]
|
|
433
|
+
- Updated dependencies [ece4dad]
|
|
434
|
+
- Updated dependencies [e9b377e]
|
|
435
|
+
- Updated dependencies [146f448]
|
|
436
|
+
- Updated dependencies [735f5c7]
|
|
437
|
+
- Updated dependencies [7303cbf]
|
|
438
|
+
- Updated dependencies [a7e18de]
|
|
439
|
+
- Updated dependencies [366f895]
|
|
440
|
+
- Updated dependencies [29ef1e1]
|
|
441
|
+
- Updated dependencies [dc75ba8]
|
|
442
|
+
- Updated dependencies [cce0aa9]
|
|
443
|
+
- Updated dependencies [e764507]
|
|
444
|
+
- Updated dependencies [cff17af]
|
|
445
|
+
- Updated dependencies [39404f3]
|
|
446
|
+
- Updated dependencies [ca1965f]
|
|
447
|
+
- Updated dependencies [8619f95]
|
|
448
|
+
- Updated dependencies [b706af9]
|
|
449
|
+
- Updated dependencies [add4360]
|
|
450
|
+
- Updated dependencies [fc9ba76]
|
|
451
|
+
- Updated dependencies [0f94cc7]
|
|
452
|
+
- Updated dependencies [a11c1a5]
|
|
453
|
+
- Updated dependencies [71f9cd1]
|
|
454
|
+
- Updated dependencies [ee17d86]
|
|
455
|
+
- Updated dependencies [cdbd920]
|
|
456
|
+
- Updated dependencies [18c432e]
|
|
457
|
+
- Updated dependencies [3c418c4]
|
|
458
|
+
- Updated dependencies [fa8715a]
|
|
459
|
+
- Updated dependencies [a933ed7]
|
|
460
|
+
- Updated dependencies [b3ca463]
|
|
461
|
+
- Updated dependencies [a933ed7]
|
|
462
|
+
- Updated dependencies [0d4a6a8]
|
|
463
|
+
- Updated dependencies [518d5e5]
|
|
464
|
+
- Updated dependencies [6643ba1]
|
|
465
|
+
- Updated dependencies [eeba2ef]
|
|
466
|
+
- Updated dependencies [ec4c4d2]
|
|
467
|
+
- Updated dependencies [424f73c]
|
|
468
|
+
- Updated dependencies [cccbe51]
|
|
469
|
+
- Updated dependencies [a8d6b1d]
|
|
470
|
+
- Updated dependencies [e4a7695]
|
|
471
|
+
- Updated dependencies [87075b1]
|
|
472
|
+
- Updated dependencies [fc58a99]
|
|
473
|
+
- Updated dependencies [14cfc00]
|
|
474
|
+
- Updated dependencies [1c6f7b4]
|
|
475
|
+
- Updated dependencies [e854a53]
|
|
476
|
+
- Updated dependencies [dfebfc8]
|
|
477
|
+
- Updated dependencies [d028b37]
|
|
478
|
+
- Updated dependencies [f7b25c5]
|
|
479
|
+
- Updated dependencies [122ef38]
|
|
480
|
+
- Updated dependencies [4a37870]
|
|
481
|
+
- Updated dependencies [428f9b2]
|
|
482
|
+
- Updated dependencies [aa7ff56]
|
|
483
|
+
- Updated dependencies [1401ae7]
|
|
484
|
+
- Updated dependencies [2fd3f1c]
|
|
485
|
+
- Updated dependencies [c41b42e]
|
|
486
|
+
- Updated dependencies [c4db311]
|
|
487
|
+
- Updated dependencies [750fff5]
|
|
488
|
+
- Updated dependencies [c19035e]
|
|
489
|
+
- Updated dependencies [ececf7a]
|
|
490
|
+
- Updated dependencies [d173125]
|
|
491
|
+
- Updated dependencies [8eeca27]
|
|
492
|
+
- Updated dependencies [8425c17]
|
|
493
|
+
- Updated dependencies [7cbe705]
|
|
494
|
+
- Updated dependencies [a5ef1d8]
|
|
495
|
+
- Updated dependencies [772d5de]
|
|
496
|
+
- Updated dependencies [ce80ec2]
|
|
497
|
+
- Updated dependencies [b372318]
|
|
498
|
+
- Updated dependencies [97a2263]
|
|
499
|
+
- Updated dependencies [29d0676]
|
|
500
|
+
- Updated dependencies [0169d49]
|
|
501
|
+
- Updated dependencies [6bd3231]
|
|
502
|
+
- Updated dependencies [d2b5ba8]
|
|
503
|
+
- Updated dependencies [b799ac5]
|
|
504
|
+
- Updated dependencies [8f74307]
|
|
505
|
+
- Updated dependencies [d23dc08]
|
|
506
|
+
- Updated dependencies [644ad50]
|
|
507
|
+
- Updated dependencies [c0714eb]
|
|
508
|
+
- Updated dependencies [9735662]
|
|
509
|
+
- Updated dependencies [bf8d129]
|
|
510
|
+
- Updated dependencies [4d5b4f8]
|
|
511
|
+
- Updated dependencies [0da7cd2]
|
|
512
|
+
- Updated dependencies [28a5c3e]
|
|
513
|
+
- Updated dependencies [4bc18e5]
|
|
514
|
+
- @objectstack/spec@17.3.0
|
|
515
|
+
- @objectstack/core@17.3.0
|
|
516
|
+
- @objectstack/plugin-auth@17.3.0
|
|
517
|
+
|
|
3
518
|
## 17.2.0
|
|
4
519
|
|
|
5
520
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -455,13 +455,20 @@ declare class SmsServicePlugin implements Plugin {
|
|
|
455
455
|
* `ObjectKernel.bootstrap`), so declaring the edge is what puts the bind
|
|
456
456
|
* ahead of the read.
|
|
457
457
|
*
|
|
458
|
-
* `sms` is the entry this card was filed about: it
|
|
459
|
-
* `PLATFORM_ALWAYS_ON_CAPABILITIES`, one past the
|
|
460
|
-
* before this declaration its correct
|
|
461
|
-
* held by nothing at all. In the window
|
|
462
|
-
* the manifest defaults — a `log` provider
|
|
463
|
-
* a default cost ceiling — while the
|
|
464
|
-
* in `sys_setting`.
|
|
458
|
+
* `sms` is the entry this card was filed about: it was added at index 6 of
|
|
459
|
+
* `PLATFORM_ALWAYS_ON_CAPABILITIES`, one past the `slice(0, 6)` prefix that
|
|
460
|
+
* was pinned there at the time, so before this declaration its correct
|
|
461
|
+
* position relative to `settings` was held by nothing at all. In the window
|
|
462
|
+
* `getNamespace('sms')` answers from the manifest defaults — a `log` provider
|
|
463
|
+
* that reports every OTP "sent" and a default cost ceiling — while the
|
|
464
|
+
* operator's saved credentials sit unread in `sys_setting`.
|
|
465
|
+
*
|
|
466
|
+
* That slice is retired (#11046): the slate pin states the rule instead —
|
|
467
|
+
* every always-on entry that is not a bind target (`queue`/`job`/`cache`/
|
|
468
|
+
* `settings`) is mounted after all of them — so `sms` is now held BY the pin
|
|
469
|
+
* rather than sitting one past it, and so is whatever is added next. That
|
|
470
|
+
* covers slate ORDER only; this declaration is still what orders the plugins,
|
|
471
|
+
* and the pin test named below is what keeps it honest.
|
|
465
472
|
*
|
|
466
473
|
* SOFT, not hard: a kernel with no settings service must still boot this
|
|
467
474
|
* plugin (the transport is buildable from options alone). ADR-0049 —
|
package/dist/index.d.ts
CHANGED
|
@@ -455,13 +455,20 @@ declare class SmsServicePlugin implements Plugin {
|
|
|
455
455
|
* `ObjectKernel.bootstrap`), so declaring the edge is what puts the bind
|
|
456
456
|
* ahead of the read.
|
|
457
457
|
*
|
|
458
|
-
* `sms` is the entry this card was filed about: it
|
|
459
|
-
* `PLATFORM_ALWAYS_ON_CAPABILITIES`, one past the
|
|
460
|
-
* before this declaration its correct
|
|
461
|
-
* held by nothing at all. In the window
|
|
462
|
-
* the manifest defaults — a `log` provider
|
|
463
|
-
* a default cost ceiling — while the
|
|
464
|
-
* in `sys_setting`.
|
|
458
|
+
* `sms` is the entry this card was filed about: it was added at index 6 of
|
|
459
|
+
* `PLATFORM_ALWAYS_ON_CAPABILITIES`, one past the `slice(0, 6)` prefix that
|
|
460
|
+
* was pinned there at the time, so before this declaration its correct
|
|
461
|
+
* position relative to `settings` was held by nothing at all. In the window
|
|
462
|
+
* `getNamespace('sms')` answers from the manifest defaults — a `log` provider
|
|
463
|
+
* that reports every OTP "sent" and a default cost ceiling — while the
|
|
464
|
+
* operator's saved credentials sit unread in `sys_setting`.
|
|
465
|
+
*
|
|
466
|
+
* That slice is retired (#11046): the slate pin states the rule instead —
|
|
467
|
+
* every always-on entry that is not a bind target (`queue`/`job`/`cache`/
|
|
468
|
+
* `settings`) is mounted after all of them — so `sms` is now held BY the pin
|
|
469
|
+
* rather than sitting one past it, and so is whatever is added next. That
|
|
470
|
+
* covers slate ORDER only; this declaration is still what orders the plugins,
|
|
471
|
+
* and the pin test named below is what keeps it honest.
|
|
465
472
|
*
|
|
466
473
|
* SOFT, not hard: a kernel with no settings service must still boot this
|
|
467
474
|
* plugin (the transport is buildable from options alone). ADR-0049 —
|
package/dist/index.js
CHANGED
|
@@ -445,13 +445,20 @@ var SmsServicePlugin = class {
|
|
|
445
445
|
* `ObjectKernel.bootstrap`), so declaring the edge is what puts the bind
|
|
446
446
|
* ahead of the read.
|
|
447
447
|
*
|
|
448
|
-
* `sms` is the entry this card was filed about: it
|
|
449
|
-
* `PLATFORM_ALWAYS_ON_CAPABILITIES`, one past the
|
|
450
|
-
* before this declaration its correct
|
|
451
|
-
* held by nothing at all. In the window
|
|
452
|
-
* the manifest defaults — a `log` provider
|
|
453
|
-
* a default cost ceiling — while the
|
|
454
|
-
* in `sys_setting`.
|
|
448
|
+
* `sms` is the entry this card was filed about: it was added at index 6 of
|
|
449
|
+
* `PLATFORM_ALWAYS_ON_CAPABILITIES`, one past the `slice(0, 6)` prefix that
|
|
450
|
+
* was pinned there at the time, so before this declaration its correct
|
|
451
|
+
* position relative to `settings` was held by nothing at all. In the window
|
|
452
|
+
* `getNamespace('sms')` answers from the manifest defaults — a `log` provider
|
|
453
|
+
* that reports every OTP "sent" and a default cost ceiling — while the
|
|
454
|
+
* operator's saved credentials sit unread in `sys_setting`.
|
|
455
|
+
*
|
|
456
|
+
* That slice is retired (#11046): the slate pin states the rule instead —
|
|
457
|
+
* every always-on entry that is not a bind target (`queue`/`job`/`cache`/
|
|
458
|
+
* `settings`) is mounted after all of them — so `sms` is now held BY the pin
|
|
459
|
+
* rather than sitting one past it, and so is whatever is added next. That
|
|
460
|
+
* covers slate ORDER only; this declaration is still what orders the plugins,
|
|
461
|
+
* and the pin test named below is what keeps it honest.
|
|
455
462
|
*
|
|
456
463
|
* SOFT, not hard: a kernel with no settings service must still boot this
|
|
457
464
|
* plugin (the transport is buildable from options alone). ADR-0049 —
|
|
@@ -541,11 +548,13 @@ var SmsServicePlugin = class {
|
|
|
541
548
|
try {
|
|
542
549
|
const payload = await settings.getNamespace("sms");
|
|
543
550
|
const values = {};
|
|
551
|
+
const sources = {};
|
|
544
552
|
for (const [k, v] of Object.entries(payload.values)) {
|
|
545
553
|
values[k] = v?.value;
|
|
554
|
+
if (v?.source) sources[k] = String(v.source);
|
|
546
555
|
}
|
|
547
556
|
this.dailyQuota?.setQuota(values.daily_quota);
|
|
548
|
-
if (!this.options.transport) this.applySmsSettings(values, ctx);
|
|
557
|
+
if (!this.options.transport) this.applySmsSettings(values, sources, ctx);
|
|
549
558
|
} catch (err) {
|
|
550
559
|
ctx.logger.warn("SmsServicePlugin: failed to apply sms settings: " + (err?.message ?? err));
|
|
551
560
|
}
|
|
@@ -608,7 +617,7 @@ var SmsServicePlugin = class {
|
|
|
608
617
|
* on the running SmsService. Incomplete credentials keep the previous
|
|
609
618
|
* transport (with a warning) so a half-saved form can't break delivery.
|
|
610
619
|
*/
|
|
611
|
-
applySmsSettings(values, ctx) {
|
|
620
|
+
applySmsSettings(values, sources, ctx) {
|
|
612
621
|
if (!this.service) return;
|
|
613
622
|
const resolved = providerFromSettings(values);
|
|
614
623
|
if (resolved.missing) {
|
|
@@ -618,7 +627,7 @@ var SmsServicePlugin = class {
|
|
|
618
627
|
return;
|
|
619
628
|
}
|
|
620
629
|
if (resolved.provider === "log") {
|
|
621
|
-
if (values.provider === "log") {
|
|
630
|
+
if (values.provider === "log" && (sources.provider ?? "default") !== "default") {
|
|
622
631
|
this.service.setTransport(new LogSmsTransport(ctx.logger), false);
|
|
623
632
|
ctx.logger.info("SmsServicePlugin: sms settings applied (provider=log; SMS will NOT be sent).");
|
|
624
633
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/sms-daily-quota.ts","../src/sms-service.ts","../src/sms-plugin.ts","../src/transports/aliyun.ts","../src/transports/twilio.ts","../src/transports/index.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nexport {\n SmsService,\n LogSmsTransport,\n maskPhoneNumber,\n normalizeSmsRecipient,\n type SmsServiceOptions,\n} from './sms-service.js';\nexport { SmsServicePlugin, type SmsServicePluginOptions } from './sms-plugin.js';\nexport {\n SmsDailyQuota,\n SMS_QUOTA_EXCEEDED_CODE,\n SMS_QUOTA_EXCEEDED_ERROR,\n normalizeDailyQuota,\n secondsUntilNextUtcMidnight,\n utcDayStamp,\n type SmsDailyQuotaDecision,\n type SmsDailyQuotaOptions,\n type NormalizedDailyQuota,\n} from './sms-daily-quota.js';\nexport {\n makeSmsTransport,\n SMS_TRANSPORT_PROVIDERS,\n isSmsTransportProvider,\n AliyunSmsTransport,\n TwilioSmsTransport,\n type SmsProviderTag,\n type MakeSmsTransportOptions,\n type AliyunSmsTransportOptions,\n type TwilioSmsTransportOptions,\n} from './transports/index.js';\n","// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Global daily SMS send quota — the COST TOTAL gate (#2814).\n *\n * ## What this adds that the per-number guard cannot\n *\n * #2780 gave the OTP endpoints a per-NUMBER budget (60s cooldown + 5 sends per\n * number per hour, `plugin-auth/src/otp-send-guard.ts`). That bounds what one\n * phone number costs. It does not bound what the DEPLOYMENT costs: an attacker\n * rotating through ten thousand distinct numbers keeps every one of them inside\n * its own budget while the daily bill has no ceiling at all — classic SMS\n * pumping / toll fraud. And the per-number guard sits in better-auth's\n * `hooks.before`, so it only ever sees the auth endpoints: `notify(channels:\n * ['sms'])` and the invitation path walk straight past it.\n *\n * This gate is therefore counted at the ONE place every outbound message\n * already funnels through — `SmsService.send()` — so OTP, invitations and the\n * messaging `sms` channel are all charged against the same budget, whatever\n * door they came in by.\n *\n * ## Where it counts (#4790's answer, reused verbatim)\n *\n * A budget is only worth what its store is worth: counted per process, a\n * declared \"2000 per day\" is really 2000×N across N nodes, and nothing says so\n * (ADR-0049 — declared ≠ enforced). So this counts through the SAME resolution\n * the auth counters use — `createLazyCounterStore` over the kernel `cache`\n * service, resolved at COUNTING time (not at plugin init, the #4772 trap),\n * with a bounded per-process fallback that announces itself. The counting\n * algorithm is `incrementFixedWindow`, imported rather than re-implemented:\n * this repo has exactly one fixed-window counter and #4790 said plainly that a\n * third copy is not wanted.\n *\n * ## The window is a UTC calendar day, twice over\n *\n * \"Daily quota\" means the calendar day, not \"24h from the first send\", so the\n * counter key carries the UTC date (`sms-daily-sends:2026-08-06`) AND the\n * window is opened with exactly the seconds remaining until the next UTC\n * midnight. Either mechanism alone would roll the budget over; together they\n * cannot disagree — a clock skew that mis-sizes the TTL still lands on a fresh\n * key at 00:00Z, and a store that ignores TTLs still starts a new key.\n *\n * ## Admission-time counting, and fail-open\n *\n * A unit is consumed when a send is ADMITTED, before the transport runs —\n * exactly like `OtpSendGuard.checkAndRecord` and\n * `createLazyCacheRateLimitStorage.consume`, both of which take the\n * post-increment count and compare it to the cap. Two consequences, stated\n * rather than discovered later: a transport failure still spends a unit (the\n * conservative direction for a COST ceiling, and the alternative is a second\n * store round-trip on every send), and attempts refused by this gate keep\n * incrementing the day's counter, so the number in the log line is \"attempts\n * today\", not \"messages delivered today\".\n *\n * Every store interaction is fail-OPEN: a cache outage must not take phone\n * sign-in down with it (#2814 requirement 4). A degraded gate is announced once\n * and then admits.\n *\n * ## What is NOT here\n *\n * The per-tenant dimension (`daily_quota_per_tenant`, keyed by\n * `organizationId`) is deliberately absent: `SendSmsInput`\n * (`@objectstack/spec/contracts/sms-service.ts`) carries no tenant identifier,\n * and inventing a second, service-local spelling of one would be exactly the\n * shadow contract AGENTS.md Prime Directive #12 forbids. See the issue thread\n * on #2814 — the tenant identifier belongs on the spec contract or nowhere.\n */\n\nimport {\n InProcessCounterStore,\n incrementFixedWindow,\n type CounterStore,\n} from '@objectstack/plugin-auth/rate-limit-storage';\n\n/**\n * The error code a quota-refused send answers with, as the `CODE: message`\n * prefix `SmsService` already uses for `VALIDATION_FAILED`.\n *\n * Deliberately the same code the per-number guard raises in `plugin-auth`\n * (`APIError('TOO_MANY_REQUESTS')`), because #2814 asks the two walls to be\n * indistinguishable from outside: an attacker must not be able to tell which\n * budget they hit, and a legitimate caller needs no more than \"not now\".\n * The message carries NO remaining-quota detail for the same reason.\n */\nexport const SMS_QUOTA_EXCEEDED_CODE = 'TOO_MANY_REQUESTS';\n\n/** The refusal text handed back on `SendSmsResult.error`. Contains no counts. */\nexport const SMS_QUOTA_EXCEEDED_ERROR = `${SMS_QUOTA_EXCEEDED_CODE}: daily SMS quota exhausted`;\n\n/** Key prefix for the day counter. Carries a date only — never a recipient. */\nconst KEY_PREFIX = 'sms-daily-sends:';\n\n/** Fraction of the quota at which the approaching-ceiling WARN fires. */\nconst NEAR_LIMIT_RATIO = 0.8;\n\ntype LoggerLike = {\n info?(msg: string, meta?: Record<string, unknown>): void;\n warn?(msg: string, meta?: Record<string, unknown>): void;\n};\n\nexport interface SmsDailyQuotaOptions {\n /**\n * Resolve the store the day counter lives in — called on EVERY check, so a\n * shared cache registered after this gate was constructed is picked up on the\n * next send rather than never (#4772/#4790). `SmsServicePlugin` supplies\n * `createLazyCounterStore(...)`; omitted ⇒ a per-process store, silently\n * (the gate constructed standalone, e.g. in tests).\n */\n resolveStore?: () => Promise<CounterStore>;\n /** Diagnostics sink. NEVER receives a message body or a recipient. */\n logger?: LoggerLike;\n /** Clock override for tests. */\n now?: () => number;\n}\n\n/** Outcome of one admission check. */\nexport interface SmsDailyQuotaDecision {\n /** Whether the send may proceed. */\n ok: boolean;\n /**\n * Attempts counted for the current UTC day AFTER this one, when the counter\n * was actually consulted. Absent when the gate is off or degraded.\n */\n count?: number;\n /** The enforced ceiling this decision was measured against (`0` ⇒ off). */\n quota?: number;\n}\n\n/** `YYYY-MM-DD` in UTC — the day the counter key is scoped to. */\nexport function utcDayStamp(now: number): string {\n return new Date(now).toISOString().slice(0, 10);\n}\n\n/**\n * Seconds from `now` to the next UTC midnight, at least 1. This is the window\n * `incrementFixedWindow` opens on the day's first send, so the counter expires\n * with the day it belongs to instead of 24h after whenever it started.\n */\nexport function secondsUntilNextUtcMidnight(now: number): number {\n const d = new Date(now);\n const next = Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate() + 1);\n return Math.max(1, Math.ceil((next - now) / 1000));\n}\n\n/**\n * Result of reading an authored quota value: the ceiling actually enforced,\n * plus the offending input when one had to be discarded.\n */\nexport interface NormalizedDailyQuota {\n /** Enforced ceiling. `0` means unlimited. Always a non-negative integer. */\n limit: number;\n /** Set when the authored value was unusable and `0` was substituted. */\n rejected?: string;\n}\n\n/**\n * Clamp an authored `sms.daily_quota` into the value actually enforced.\n *\n * **This lives on the CONSUMER side on purpose (#5932).** It was written while\n * `min` was inert — `SettingsService.validatePatch` declared five value\n * constraints and read only `pattern`, so a `min: 0` filtered nothing and\n * negative, fractional and outright non-numeric values all reached a reader\n * intact. #5932 has since closed the producer half: the declared window is\n * enforced on the save path and on the `OS_*` env path, so `daily_quota: -1`\n * is now refused at `PUT /api/settings/sms` with a `min_value` FieldError.\n *\n * The clamp stays, and not out of sentiment — three of its inputs are still\n * genuinely reachable, so removing it would re-open a live hole rather than\n * delete a dead one:\n *\n * - **Non-numeric values** (`true`, `'unlimited'`, `{ n: 5 }`). The window\n * check deliberately does not judge a value's SHAPE — that is `invalid_type`,\n * a different constraint with a different owner — so these still arrive.\n * - **Fractional counts.** `100.5` is inside `min: 0` and always was; flooring\n * is this reader's rule, not the manifest's.\n * - **Historical rows.** The save-path check runs under the TOUCH gate, so a\n * value stored before the gate existed survives until someone re-writes that\n * key — deliberately, so a workspace carrying drift is not locked out of its\n * own settings page.\n *\n * What changed is the failure mode this defends against, not whether it is\n * needed: a bad value is now refused where it is authored (loudly, at the\n * producer, per ADR-0049), and this clamp is what keeps a value that predates\n * or sidesteps that gate from becoming behaviour.\n *\n * The rules, and why each is the safe direction for a paid channel:\n *\n * - **absent / empty string** → `0` (unlimited), quietly. That is \"the operator\n * has not configured a ceiling\", which is the shipped default, not an error.\n * - **finite number ≥ 0** → `Math.floor(v)`. A fractional message count is\n * rounded DOWN, the stricter direction for a cost ceiling, and is not worth a\n * diagnostic — `100.5` unambiguously means \"at most 100 messages\".\n * - **negative, NaN, ±Infinity, or a non-numeric type** → `0` (unlimited) plus\n * a named rejection the caller logs LOUDLY.\n *\n * That last rule is the one worth arguing. Two other readings exist and both\n * are worse here. Refusing to send at all turns one typo in a settings form\n * into a total outage of phone sign-in — the precise failure #2814 requirement\n * 4 rules out (\"配额闸不能把登录拖下水\"), and the same reasoning `SettingsService`\n * applies when it ignores a rejected `OS_*` override rather than acting on it.\n * Substituting some other default invents a ceiling nobody declared and hides\n * the typo behind plausible behaviour (#5152's lesson, where a typo'd\n * `invite_only` read as `auto` left an operator believing a wall was up).\n * Ignoring the value and SAYING SO leaves the deployment exactly where it was\n * before the bad edit, with a line naming the value to fix.\n */\nexport function normalizeDailyQuota(raw: unknown): NormalizedDailyQuota {\n if (raw === undefined || raw === null) return { limit: 0 };\n if (typeof raw === 'string') {\n const trimmed = raw.trim();\n if (trimmed.length === 0) return { limit: 0 };\n const parsed = Number(trimmed);\n if (Number.isFinite(parsed) && parsed >= 0) return { limit: Math.floor(parsed) };\n return { limit: 0, rejected: trimmed };\n }\n if (typeof raw === 'number') {\n if (Number.isFinite(raw) && raw >= 0) return { limit: Math.floor(raw) };\n return { limit: 0, rejected: String(raw) };\n }\n return { limit: 0, rejected: typeof raw === 'object' ? JSON.stringify(raw) : String(raw) };\n}\n\n/**\n * The global daily send ceiling, counted once per admitted send.\n *\n * Constructed by `SmsServicePlugin` and handed to `SmsService`; `setQuota` is\n * called on every `sms` settings change so an admin edit takes effect without a\n * restart (same live-swap contract as the transport).\n */\nexport class SmsDailyQuota {\n private limit = 0;\n private readonly resolveStore: () => Promise<CounterStore>;\n private readonly logger?: LoggerLike;\n private readonly now: () => number;\n\n /**\n * Per-process fallback used when no resolver was supplied at all (the gate\n * constructed standalone). The SAME bounded store the auth counters degrade\n * to — one fallback implementation across the repo, not a second one that can\n * drift (#4790).\n */\n private readonly fallback = new InProcessCounterStore();\n\n /** The last authored value reported as unusable — deduped, per value. */\n private reportedRejection?: string;\n /** UTC day stamp the approaching-ceiling WARN has already fired for. */\n private nearLimitWarnedFor?: string;\n /** UTC day stamp the ceiling-reached WARN has already fired for. */\n private exceededWarnedFor?: string;\n /** Store-outage WARN is once per process — see `checkAndRecord`. */\n private degradedWarned = false;\n\n constructor(options: SmsDailyQuotaOptions = {}) {\n this.logger = options.logger;\n this.now = options.now ?? Date.now;\n this.resolveStore = options.resolveStore ?? (async () => this.fallback);\n }\n\n /**\n * Apply an authored `sms.daily_quota`. Anything unusable degrades to\n * \"unlimited\" and is reported once per distinct offending value — see\n * {@link normalizeDailyQuota} for why that is the safe direction.\n */\n setQuota(raw: unknown): void {\n const { limit, rejected } = normalizeDailyQuota(raw);\n this.limit = limit;\n if (rejected !== undefined && rejected !== this.reportedRejection) {\n this.reportedRejection = rejected;\n this.logger?.warn?.(\n `[sms] daily_quota value '${rejected}' is not a usable message count — the daily SMS quota is ` +\n 'NOT enforced until it is corrected. Use a non-negative whole number, or 0 for \"no limit\".',\n );\n }\n }\n\n /** The ceiling actually in force (`0` ⇒ unlimited). @internal test seam */\n get enforcedQuota(): number {\n return this.limit;\n }\n\n /**\n * Charge one send against today's budget and answer whether it may proceed.\n *\n * Never throws: a store outage fails OPEN (announced once per process), for\n * the reason in the file header — an SMS cost ceiling that can block sign-in\n * is a worse problem than the one it solves.\n */\n async checkAndRecord(): Promise<SmsDailyQuotaDecision> {\n if (this.limit <= 0) return { ok: true, quota: 0 };\n const now = this.now();\n const day = utcDayStamp(now);\n try {\n const store = await this.resolveStore();\n const { count } = await incrementFixedWindow(\n store,\n KEY_PREFIX + day,\n secondsUntilNextUtcMidnight(now),\n now,\n );\n\n if (count > this.limit) {\n if (this.exceededWarnedFor !== day) {\n this.exceededWarnedFor = day;\n this.logger?.warn?.(\n `[sms] daily SMS quota reached — further sends are refused until 00:00 UTC.`,\n { day, count, quota: this.limit },\n );\n }\n return { ok: false, count, quota: this.limit };\n }\n\n if (count >= Math.ceil(this.limit * NEAR_LIMIT_RATIO) && this.nearLimitWarnedFor !== day) {\n this.nearLimitWarnedFor = day;\n this.logger?.warn?.(\n `[sms] daily SMS quota is ${Math.round(NEAR_LIMIT_RATIO * 100)}% consumed.`,\n { day, count, quota: this.limit },\n );\n }\n return { ok: true, count, quota: this.limit };\n } catch (err) {\n if (!this.degradedWarned) {\n this.degradedWarned = true;\n this.logger?.warn?.(\n '[sms] daily SMS quota counter is unreadable (' +\n String((err as Error)?.message ?? err) +\n ') — the gate is FAILING OPEN and today\\'s spend is unbounded until the counter store recovers. ' +\n 'Sign-in is deliberately not taken down with it (#2814).',\n );\n }\n return { ok: true };\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n ISmsService,\n ISmsTransport,\n NormalizedSmsMessage,\n SendSmsInput,\n SendSmsResult,\n SmsTransportSendResult,\n} from '@objectstack/spec/contracts';\nimport { SMS_QUOTA_EXCEEDED_ERROR, type SmsDailyQuota } from './sms-daily-quota.js';\n\n/**\n * Normalize + validate a recipient phone number. Accepts E.164 and common\n * human formats (spaces / dashes / dots / parens are stripped). Returns\n * `undefined` when the result doesn't look like a phone number.\n *\n * Same shape rule as plugin-auth's `normalizePhoneNumber` — 6-15 digits\n * with an optional leading `+` (kept local: the two packages must not\n * depend on each other).\n */\nexport function normalizeSmsRecipient(raw: string): string | undefined {\n const stripped = String(raw ?? '').replace(/[\\s\\-().]/g, '');\n return /^\\+?[0-9]{6,15}$/.test(stripped) ? stripped : undefined;\n}\n\n/**\n * Mask a phone number for log lines: keep the prefix (country-code-ish) and\n * the last two digits, hide the middle. `+8613812345678` → `+8613******78`.\n * SMS logging policy: masked recipient + status ONLY — never the body\n * (OTP codes travel in it; see the ISmsService contract header).\n */\nexport function maskPhoneNumber(phone: string): string {\n const p = String(phone ?? '');\n if (p.length <= 6) return `${p.slice(0, 2)}****`;\n return `${p.slice(0, 5)}${'*'.repeat(Math.max(2, p.length - 7))}${p.slice(-2)}`;\n}\n\n/**\n * Development transport — never actually sends. Logs the masked recipient\n * (and, OUTSIDE production only, the message body so local OTP flows are\n * testable) and returns a synthetic message id.\n *\n * The production-body suppression is a hard rule from #2780: OTP codes must\n * never land in logs. In dev the body IS the delivery — same pattern as the\n * auth magic-link / invitation URLs, which are printed in dev only.\n */\nexport class LogSmsTransport implements ISmsTransport {\n private counter = 0;\n constructor(private readonly logger?: { info: (msg: string, meta?: any) => void }) {}\n async send(message: NormalizedSmsMessage): Promise<SmsTransportSendResult> {\n const messageId = `dev-sms-${Date.now()}-${++this.counter}`;\n const dev = (globalThis as any)?.process?.env?.NODE_ENV !== 'production';\n this.logger?.info(\n `[LogSmsTransport] would send SMS to ${maskPhoneNumber(message.to)}` +\n (dev ? ` — body: ${message.body}` : ' (body suppressed outside dev)'),\n { messageId },\n );\n return { messageId, response: 'logged' };\n }\n}\n\nexport interface SmsServiceOptions {\n transport: ISmsTransport;\n /**\n * Whether `transport` is a real provider (Aliyun / Twilio / injected).\n * `false` = development log fallback; surfaced via `isConfigured()` so\n * consumers can gate SMS-dependent features in production.\n */\n configured: boolean;\n /** Retry attempts on transport throw. Default 0 (no retry). */\n retries?: number;\n /** Logger for diagnostic output. NEVER receives message bodies. */\n logger?: {\n info: (msg: string, meta?: any) => void;\n warn: (msg: string, meta?: any) => void;\n };\n /**\n * The deployment-wide daily send ceiling (#2814). Charged once per admitted\n * send, HERE rather than at the auth endpoints, so OTP, invitations and the\n * messaging `sms` channel are all counted against the one budget — see\n * `sms-daily-quota.ts`. Omitted ⇒ no total-cost gate (the pre-#2814\n * behaviour).\n */\n dailyQuota?: SmsDailyQuota;\n}\n\n/**\n * Concrete ISmsService implementation.\n *\n * Flow: validate + normalize input → transport.send() (with optional\n * retry) → SendSmsResult. Deliberately NO persistence and NO body logging —\n * see the contract header in `@objectstack/spec/contracts/sms-service.ts`.\n */\nexport class SmsService implements ISmsService {\n constructor(public options: SmsServiceOptions) {\n if (!options.transport) throw new Error('SmsService: transport is required');\n }\n\n /**\n * Hot-swap the underlying transport (settings namespace changed). The\n * `configured` flag travels with the transport.\n */\n setTransport(transport: ISmsTransport, configured: boolean): void {\n this.options.transport = transport;\n this.options.configured = configured;\n }\n\n isConfigured(): boolean {\n return this.options.configured;\n }\n\n async send(input: SendSmsInput): Promise<SendSmsResult> {\n const to = normalizeSmsRecipient(input?.to ?? '');\n if (!to) {\n throw new Error(`VALIDATION_FAILED: '${maskPhoneNumber(String(input?.to ?? ''))}' is not a valid phone number`);\n }\n const body = String(input?.body ?? '').trim();\n if (!body && !input?.templateId && !input?.templateParams) {\n throw new Error('VALIDATION_FAILED: body (or templateId/templateParams) is required');\n }\n\n const normalized: NormalizedSmsMessage = {\n to,\n body,\n ...(input.templateId ? { templateId: input.templateId } : {}),\n ...(input.templateParams ? { templateParams: input.templateParams } : {}),\n };\n\n const id = `sms-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n\n // #2814 — the deployment's daily cost ceiling, charged after the input is\n // known to be a real send (a malformed recipient never spent anything, so\n // it must not spend a unit either) and before the transport, which is the\n // only ordering that actually caps spend. Refusal is reported as a failed\n // send carrying the SAME `TOO_MANY_REQUESTS` code the per-number guard\n // raises, with no remaining-quota detail — outside, the two walls are\n // indistinguishable on purpose.\n //\n // Measured caveat (#6039): on the auth OTP path that code does NOT reach\n // the HTTP caller today. `AuthManager.deliverPhoneOtp` rethrows a plain\n // `Error`, and better-call answers 500 for anything that is not an\n // `APIError` — so the endpoint returns 500 while the per-number guard on\n // the same endpoint returns 429. Closing that needs a change inside\n // plugin-auth, which is why it is filed rather than papered over here.\n if (this.options.dailyQuota) {\n const decision = await this.options.dailyQuota.checkAndRecord();\n if (!decision.ok) {\n this.options.logger?.warn?.(\n `[SmsService] send to ${maskPhoneNumber(to)} refused: daily quota exhausted`,\n );\n return { id, status: 'failed', error: SMS_QUOTA_EXCEEDED_ERROR };\n }\n }\n const maxAttempts = (this.options.retries ?? 0) + 1;\n let lastError: unknown;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const result = await this.options.transport.send(normalized);\n this.options.logger?.info(\n `[SmsService] sent to ${maskPhoneNumber(to)} (messageId=${result.messageId})`,\n );\n return { id, status: 'sent', messageId: result.messageId };\n } catch (err) {\n lastError = err;\n if (attempt < maxAttempts) {\n await new Promise((r) => setTimeout(r, Math.min(2000, 100 * 2 ** (attempt - 1))));\n }\n }\n }\n const errMessage = String((lastError as Error)?.message ?? lastError ?? 'send failed').slice(0, 500);\n this.options.logger?.warn(\n `[SmsService] send to ${maskPhoneNumber(to)} failed: ${errMessage}`,\n );\n return { id, status: 'failed', error: errMessage };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport type { ISmsTransport } from '@objectstack/spec/contracts';\nimport { createLazyCounterStore, type CounterStore } from '@objectstack/plugin-auth/rate-limit-storage';\nimport { SmsService, LogSmsTransport, maskPhoneNumber, normalizeSmsRecipient } from './sms-service.js';\nimport { SmsDailyQuota } from './sms-daily-quota.js';\nimport { makeSmsTransport, type SmsProviderTag } from './transports/index.js';\n\n/**\n * Plugin configuration. Mirrors EmailServicePluginOptions: a directly\n * injected transport wins, then `provider` + credentials, then the\n * development `LogSmsTransport` fallback (no real send).\n */\nexport interface SmsServicePluginOptions {\n /** Pluggable delivery transport. Overrides `provider`/credentials. */\n transport?: ISmsTransport;\n /** Provider tag — `'log' | 'aliyun' | 'twilio'`. Default `'log'`. */\n provider?: SmsProviderTag;\n /** Provider-specific credentials/options (see transport option types). */\n providerOptions?: Record<string, unknown>;\n /** Retry attempts on transport throw. Default 0. */\n retries?: number;\n}\n\n/** Translate an `sms` settings-namespace snapshot into transport inputs. */\nfunction providerFromSettings(values: Record<string, unknown>): {\n provider: SmsProviderTag;\n options: Record<string, unknown>;\n missing?: string;\n} {\n const provider = String(values.provider ?? 'log') as SmsProviderTag;\n const str = (k: string): string | undefined => {\n const v = values[k];\n return typeof v === 'string' && v.trim().length > 0 ? v.trim() : undefined;\n };\n if (provider === 'aliyun') {\n const accessKeyId = str('aliyun_access_key_id');\n const accessKeySecret = str('aliyun_access_key_secret');\n const signName = str('aliyun_sign_name');\n if (!accessKeyId || !accessKeySecret || !signName) {\n return { provider, options: {}, missing: 'aliyun_access_key_id / aliyun_access_key_secret / aliyun_sign_name' };\n }\n return {\n provider,\n options: {\n accessKeyId,\n accessKeySecret,\n signName,\n ...(str('aliyun_template_code') ? { defaultTemplateCode: str('aliyun_template_code') } : {}),\n },\n };\n }\n if (provider === 'twilio') {\n const accountSid = str('twilio_account_sid');\n const authToken = str('twilio_auth_token');\n const from = str('twilio_from_number');\n const messagingServiceSid = str('twilio_messaging_service_sid');\n if (!accountSid || !authToken || (!from && !messagingServiceSid)) {\n return { provider, options: {}, missing: 'twilio_account_sid / twilio_auth_token / twilio_from_number (or messaging service SID)' };\n }\n return {\n provider,\n options: {\n accountSid,\n authToken,\n ...(from ? { from } : {}),\n ...(messagingServiceSid ? { messagingServiceSid } : {}),\n },\n };\n }\n return { provider: 'log', options: {} };\n}\n\n/**\n * SmsServicePlugin — registers the `sms` service (#2780).\n *\n * Lifecycle:\n * - `init`: build transport (injected → provider+credentials →\n * LogSmsTransport fallback); register the SmsService so dependents\n * (auth OTP, the messaging `sms` channel) can resolve it.\n * - `start` (kernel:ready): bind the `sms` settings namespace so the\n * admin UI can live-swap the provider without a restart, and register\n * the `sms/test` action. Env-locked keys (OS_SMS_*) still win at the\n * settings-resolver level.\n *\n * Deliberately NO persistence objects: SMS bodies carry OTP codes — see the\n * ISmsService contract header.\n */\nexport class SmsServicePlugin implements Plugin {\n name = 'com.objectstack.service.sms';\n /**\n * Services init() registers on every path (ADR-0116, #4131) — lets the\n * kernel name this plugin when a consumer requires one before it inits.\n */\n providesServices = ['sms'];\n /**\n * Order-if-present on the settings service (ADR-0116, #10250).\n *\n * `start()` registers a `kernel:ready` hook that reads the `sms` namespace —\n * provider credentials AND the daily cost ceiling. `SettingsServicePlugin`\n * binds its data engine from ITS `kernel:ready` hook, registered in ITS\n * `start()`, so the plugin that starts first registers the earlier hook and\n * the earlier hook runs first. Start order is the topological order over this\n * declaration (`resolvePluginOrder`, used for BOTH phases in\n * `ObjectKernel.bootstrap`), so declaring the edge is what puts the bind\n * ahead of the read.\n *\n * `sms` is the entry this card was filed about: it sits at index 6 of\n * `PLATFORM_ALWAYS_ON_CAPABILITIES`, one past the pinned `slice(0, 6)`, so\n * before this declaration its correct position relative to `settings` was\n * held by nothing at all. In the window `getNamespace('sms')` answers from\n * the manifest defaults — a `log` provider that reports every OTP \"sent\" and\n * a default cost ceiling — while the operator's saved credentials sit unread\n * in `sys_setting`.\n *\n * SOFT, not hard: a kernel with no settings service must still boot this\n * plugin (the transport is buildable from options alone). ADR-0049 —\n * declared is enforced: `serve-settings-ordering.pin.test.ts` boots a kernel\n * with the readers registered BEFORE settings and proves the order moves.\n */\n optionalDependencies = ['com.objectstack.service.settings'];\n version = '1.0.0';\n type = 'standard' as const;\n\n private readonly options: SmsServicePluginOptions;\n private service?: SmsService;\n private dailyQuota?: SmsDailyQuota;\n\n constructor(options: SmsServicePluginOptions = {}) {\n this.options = options;\n }\n\n /**\n * Build the daily cost gate (#2814) over the kernel `cache` service.\n *\n * `resolveCache` is copied in shape from `AuthPlugin.init()` on purpose, for\n * the two reasons stated there: the `cache` service is registered ASYNC (so\n * `getService` throws for it and `getServiceAsync` is the only accessor that\n * works), and resolution has to happen when a counter is CONSUMED rather than\n * at init, or a deployment that registers its cache after this plugin freezes\n * a \"no shared store\" answer for the life of the process (#4772). The\n * degraded case is announced by `createLazyCounterStore` itself, named for\n * this subject.\n */\n private buildDailyQuota(ctx: PluginContext): SmsDailyQuota {\n const resolveCache = async (): Promise<CounterStore | undefined> => {\n let cache: any;\n try {\n cache = await (ctx as { getServiceAsync?: (n: string) => Promise<unknown> })\n .getServiceAsync?.('cache');\n } catch {\n return undefined;\n }\n if (cache && typeof cache.get === 'function' && typeof cache.set === 'function') return cache;\n return undefined;\n };\n return new SmsDailyQuota({\n resolveStore: createLazyCounterStore({\n resolveCache,\n logger: ctx.logger,\n logPrefix: '[sms]',\n subject: 'daily SMS send quota (#2814)',\n degradedImpact:\n 'The ceiling is still enforced, but PER NODE: an N-node deployment can spend up to N× the ' +\n 'configured number of PAID SMS per day, which is exactly the total-cost hole this gate exists to close',\n }),\n logger: ctx.logger,\n });\n }\n\n private resolveInitialTransport(ctx: PluginContext): { transport: ISmsTransport; configured: boolean } {\n if (this.options.transport) return { transport: this.options.transport, configured: true };\n const provider = this.options.provider ?? 'log';\n if (provider === 'log') return { transport: new LogSmsTransport(ctx.logger), configured: false };\n try {\n return {\n transport: makeSmsTransport({ provider, options: this.options.providerOptions, logger: ctx.logger }),\n configured: true,\n };\n } catch (err: any) {\n // Incomplete constructor credentials must not take the kernel down —\n // fall back to the dev transport; the settings bind (kernel:ready)\n // can still swap in a working provider.\n ctx.logger.warn(\n `SmsServicePlugin: provider='${provider}' selected but transport build failed (${err?.message ?? err}) — falling back to LogSmsTransport.`,\n );\n return { transport: new LogSmsTransport(ctx.logger), configured: false };\n }\n }\n\n async init(ctx: PluginContext): Promise<void> {\n const { transport, configured } = this.resolveInitialTransport(ctx);\n if (!configured) {\n ctx.logger.info('SmsServicePlugin: no provider configured — using LogSmsTransport (SMS will NOT be sent)');\n } else {\n ctx.logger.info(`SmsServicePlugin: using '${this.options.provider ?? 'custom'}' provider`);\n }\n this.dailyQuota = this.buildDailyQuota(ctx);\n this.service = new SmsService({\n transport,\n configured,\n retries: this.options.retries,\n logger: ctx.logger,\n dailyQuota: this.dailyQuota,\n });\n ctx.registerService('sms', this.service);\n ctx.logger.info('SmsServicePlugin: sms service registered');\n }\n\n async start(ctx: PluginContext): Promise<void> {\n ctx.hook('kernel:ready', async () => {\n if (!this.service) return;\n try {\n const settings = ctx.getService<any>('settings');\n if (!settings || typeof settings.getNamespace !== 'function') return;\n\n const applySettings = async () => {\n try {\n const payload = await settings.getNamespace('sms');\n const values: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(payload.values as Record<string, any>)) {\n values[k] = v?.value;\n }\n // #2814 — the daily cost ceiling binds for EVERY composition,\n // including a host-injected transport: \"how much may this\n // deployment spend today\" is an operator policy about the\n // deployment, not a property of whichever transport delivers.\n // Read by VALUE, never by `ResolvedSettingValue.source` — an\n // env-locked `OS_SMS_DAILY_QUOTA` and an admin-saved row are the\n // same instruction to this reader (#5536).\n this.dailyQuota?.setQuota(values.daily_quota);\n // A host-injected transport, by contrast, IS authoritative — the\n // settings form only manages the provider-tag path.\n if (!this.options.transport) this.applySmsSettings(values, ctx);\n } catch (err: any) {\n ctx.logger.warn('SmsServicePlugin: failed to apply sms settings: ' + (err?.message ?? err));\n }\n };\n await applySettings();\n if (typeof settings.subscribe === 'function') {\n settings.subscribe('sms', () => { void applySettings(); });\n ctx.logger.info('SmsServicePlugin: bound to settings:changed for namespace=sms');\n }\n\n // `sms/test` action — validate the (possibly unsaved) form values by\n // sending a real test message through a one-shot transport, mirroring\n // the `mail/test` handler in EmailServicePlugin. Still skipped when the\n // host injected its own transport: the form's provider fields describe\n // nothing that composition uses, so testing them would be theatre.\n if (!this.options.transport && typeof settings.registerAction === 'function') {\n const svc = this.service;\n settings.registerAction('sms', 'test', async ({ values, payload, ctx: actionCtx }: any) => {\n const overrides = (payload && typeof payload === 'object' && payload.values && typeof payload.values === 'object')\n ? payload.values\n : (payload ?? {});\n const merged: Record<string, unknown> = { ...(values ?? {}), ...overrides };\n const rawTo = (actionCtx?.body?.to as string | undefined) ?? (payload?.to as string | undefined);\n const to = rawTo ? normalizeSmsRecipient(rawTo) : undefined;\n if (!to) {\n return { ok: false, severity: 'error', message: 'Provide a valid \"to\" phone number (E.164 recommended).' };\n }\n\n const resolved = providerFromSettings(merged);\n if (resolved.missing) {\n return { ok: false, severity: 'error', message: `${resolved.provider}: missing ${resolved.missing}.` };\n }\n\n let target: SmsService = svc;\n if (resolved.provider !== 'log') {\n try {\n const transport = makeSmsTransport({ provider: resolved.provider, options: resolved.options, logger: ctx.logger });\n target = new SmsService({ transport, configured: true, logger: ctx.logger });\n } catch (err: any) {\n return { ok: false, severity: 'error', message: `Failed to build ${resolved.provider} transport: ${err?.message ?? String(err)}` };\n }\n }\n\n try {\n const result = await target.send({\n to,\n body: 'ObjectStack SMS test message.',\n templateParams: { content: 'ObjectStack SMS test message.' },\n });\n if (result.status === 'failed') {\n return { ok: false, severity: 'error', message: result.error ?? 'Send failed.' };\n }\n return {\n ok: true,\n severity: 'info',\n message: `Sent test SMS to ${maskPhoneNumber(to)} via ${resolved.provider} (id=${result.messageId ?? result.id}).`,\n };\n } catch (err: any) {\n return { ok: false, severity: 'error', message: err?.message ?? String(err) };\n }\n });\n }\n } catch {\n // settings service not registered — constructor opts remain authoritative.\n }\n });\n }\n\n /**\n * Translate the `sms` settings snapshot into a transport and hot-swap it\n * on the running SmsService. Incomplete credentials keep the previous\n * transport (with a warning) so a half-saved form can't break delivery.\n */\n private applySmsSettings(values: Record<string, unknown>, ctx: PluginContext): void {\n if (!this.service) return;\n const resolved = providerFromSettings(values);\n if (resolved.missing) {\n ctx.logger.warn(\n `SmsServicePlugin: provider='${resolved.provider}' selected but ${resolved.missing} is empty — transport NOT rebuilt.`,\n );\n return;\n }\n if (resolved.provider === 'log') {\n // Downgrade to the dev transport only when the operator explicitly\n // selected `log`; an unset namespace keeps the constructor opts.\n if (values.provider === 'log') {\n this.service.setTransport(new LogSmsTransport(ctx.logger), false);\n ctx.logger.info('SmsServicePlugin: sms settings applied (provider=log; SMS will NOT be sent).');\n }\n return;\n }\n try {\n const transport = makeSmsTransport({ provider: resolved.provider, options: resolved.options, logger: ctx.logger });\n this.service.setTransport(transport, true);\n ctx.logger.info(`SmsServicePlugin: transport rebuilt from settings (provider=${resolved.provider}).`);\n } catch (err: any) {\n ctx.logger.warn('SmsServicePlugin: failed to rebuild transport: ' + (err?.message ?? err));\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { createHash, createHmac, randomUUID } from 'node:crypto';\nimport type { ISmsTransport, NormalizedSmsMessage, SmsTransportSendResult } from '@objectstack/spec/contracts';\n\nexport interface AliyunSmsTransportOptions {\n accessKeyId: string;\n accessKeySecret: string;\n /** 短信签名 SignName — the registered sender signature, e.g. `阿里云短信测试`. */\n signName: string;\n /**\n * Default 模板 TemplateCode used when the input carries no `templateId`\n * (Aliyun only delivers pre-registered templates — free-form bodies are\n * refused by the API). A catch-all template with a single `${content}`\n * variable makes generic notification sends possible.\n */\n defaultTemplateCode?: string;\n /** API endpoint host. Default `dysmsapi.aliyuncs.com`. */\n endpoint?: string;\n /** Injectable fetch for tests. */\n fetchImpl?: typeof fetch;\n}\n\nconst API_VERSION = '2017-05-25';\nconst ALGORITHM = 'ACS3-HMAC-SHA256';\n\nconst sha256Hex = (s: string): string => createHash('sha256').update(s, 'utf8').digest('hex');\nconst hmac256Hex = (key: string, s: string): string => createHmac('sha256', key).update(s, 'utf8').digest('hex');\n\n/** RFC 3986 percent-encoding (Aliyun requires `%20`, `%2A`, `%7E` handling). */\nconst encode = (s: string): string =>\n encodeURIComponent(s)\n .replace(/\\+/g, '%20')\n .replace(/\\*/g, '%2A')\n .replace(/%7E/g, '~');\n\n/**\n * Aliyun SMS (dysmsapi `SendSms`) transport, signed with the current\n * ACS3-HMAC-SHA256 scheme — plain `fetch` + `node:crypto`, no vendor SDK.\n *\n * Aliyun is template-only: the transport sends `templateId` (falling back to\n * the configured default TemplateCode) with `templateParams` (falling back to\n * `{ content: body }` for the catch-all-template pattern). The rendered\n * `body` itself is never transmitted outside `TemplateParam`.\n */\nexport class AliyunSmsTransport implements ISmsTransport {\n private readonly endpoint: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(private readonly options: AliyunSmsTransportOptions) {\n if (!options.accessKeyId || !options.accessKeySecret) {\n throw new Error('AliyunSmsTransport: accessKeyId and accessKeySecret are required');\n }\n if (!options.signName) {\n throw new Error('AliyunSmsTransport: signName is required');\n }\n this.endpoint = options.endpoint ?? 'dysmsapi.aliyuncs.com';\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n async send(message: NormalizedSmsMessage): Promise<SmsTransportSendResult> {\n const templateCode = message.templateId ?? this.options.defaultTemplateCode;\n if (!templateCode) {\n throw new Error(\n 'AliyunSmsTransport: Aliyun requires a template — pass templateId or configure a default template code',\n );\n }\n const templateParam = JSON.stringify(message.templateParams ?? { content: message.body });\n\n const query: Record<string, string> = {\n PhoneNumbers: message.to,\n SignName: this.options.signName,\n TemplateCode: templateCode,\n TemplateParam: templateParam,\n };\n const canonicalQuery = Object.keys(query)\n .sort()\n .map((k) => `${encode(k)}=${encode(query[k])}`)\n .join('&');\n\n const bodyHash = sha256Hex(''); // POST with all parameters in the query string\n const headers: Record<string, string> = {\n host: this.endpoint,\n 'x-acs-action': 'SendSms',\n 'x-acs-content-sha256': bodyHash,\n 'x-acs-date': new Date().toISOString().replace(/\\.\\d{3}Z$/, 'Z'),\n 'x-acs-signature-nonce': randomUUID(),\n 'x-acs-version': API_VERSION,\n };\n const signedHeaderNames = Object.keys(headers).sort();\n const canonicalHeaders = signedHeaderNames.map((k) => `${k}:${headers[k].trim()}\\n`).join('');\n const signedHeaders = signedHeaderNames.join(';');\n\n const canonicalRequest = ['POST', '/', canonicalQuery, canonicalHeaders, signedHeaders, bodyHash].join('\\n');\n const stringToSign = `${ALGORITHM}\\n${sha256Hex(canonicalRequest)}`;\n const signature = hmac256Hex(this.options.accessKeySecret, stringToSign);\n\n const response = await this.fetchImpl(`https://${this.endpoint}/?${canonicalQuery}`, {\n method: 'POST',\n headers: {\n ...headers,\n Authorization: `${ALGORITHM} Credential=${this.options.accessKeyId},SignedHeaders=${signedHeaders},Signature=${signature}`,\n },\n });\n\n let payload: any = {};\n try { payload = await response.json(); } catch { /* non-JSON error body */ }\n if (!response.ok || payload?.Code !== 'OK') {\n const code = payload?.Code ?? `HTTP_${response.status}`;\n const detail = payload?.Message ?? response.statusText ?? 'request failed';\n throw new Error(`Aliyun SendSms failed (${code}): ${detail}`);\n }\n return { messageId: String(payload.BizId ?? payload.RequestId ?? ''), response: payload.RequestId };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ISmsTransport, NormalizedSmsMessage, SmsTransportSendResult } from '@objectstack/spec/contracts';\n\nexport interface TwilioSmsTransportOptions {\n accountSid: string;\n authToken: string;\n /** Sender number (E.164). One of `from` / `messagingServiceSid` is required. */\n from?: string;\n /** Twilio Messaging Service SID (alternative to a fixed `from` number). */\n messagingServiceSid?: string;\n /** API base URL override (tests). Default `https://api.twilio.com`. */\n baseUrl?: string;\n /** Injectable fetch for tests. */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Twilio Programmable Messaging transport — a single `POST\n * /2010-04-01/Accounts/{sid}/Messages.json` with HTTP Basic auth. Plain\n * `fetch`, no vendor SDK. Free-form: delivers `body` verbatim.\n */\nexport class TwilioSmsTransport implements ISmsTransport {\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(private readonly options: TwilioSmsTransportOptions) {\n if (!options.accountSid || !options.authToken) {\n throw new Error('TwilioSmsTransport: accountSid and authToken are required');\n }\n if (!options.from && !options.messagingServiceSid) {\n throw new Error('TwilioSmsTransport: one of from / messagingServiceSid is required');\n }\n this.baseUrl = (options.baseUrl ?? 'https://api.twilio.com').replace(/\\/$/, '');\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n async send(message: NormalizedSmsMessage): Promise<SmsTransportSendResult> {\n const form = new URLSearchParams({\n To: message.to,\n Body: message.body,\n ...(this.options.messagingServiceSid\n ? { MessagingServiceSid: this.options.messagingServiceSid }\n : { From: this.options.from as string }),\n });\n const auth = Buffer.from(`${this.options.accountSid}:${this.options.authToken}`).toString('base64');\n const response = await this.fetchImpl(\n `${this.baseUrl}/2010-04-01/Accounts/${encodeURIComponent(this.options.accountSid)}/Messages.json`,\n {\n method: 'POST',\n headers: {\n Authorization: `Basic ${auth}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: form.toString(),\n },\n );\n\n let payload: any = {};\n try { payload = await response.json(); } catch { /* non-JSON error body */ }\n if (!response.ok) {\n const code = payload?.code ?? `HTTP_${response.status}`;\n const detail = payload?.message ?? response.statusText ?? 'request failed';\n throw new Error(`Twilio send failed (${code}): ${detail}`);\n }\n return { messageId: String(payload.sid ?? ''), response: payload.status };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ISmsTransport } from '@objectstack/spec/contracts';\nimport { LogSmsTransport } from '../sms-service.js';\nimport { AliyunSmsTransport } from './aliyun.js';\nimport { TwilioSmsTransport } from './twilio.js';\n\nexport { AliyunSmsTransport, type AliyunSmsTransportOptions } from './aliyun.js';\nexport { TwilioSmsTransport, type TwilioSmsTransportOptions } from './twilio.js';\n\n/**\n * The provider vocabulary — every tag `makeSmsTransport` below can build, and\n * nothing else. It is the **one** literal: the `SmsProviderTag` type is derived\n * from it, the `switch` is exhaustive over it, and callers that have to judge an\n * operator-supplied provider string (the CLI's `sms` capability arm, #5713) read\n * it from here rather than restating the list.\n *\n * Two literals describing one vocabulary is how the mail settings dropdown and\n * the mail transports drifted apart (#5094) — `sendgrid`/`ses` were offered with\n * no transport behind them while `resend` had a working transport nobody could\n * pick. The SMS boot path had the same shape from the other side: `os serve`\n * passed `OS_SMS_PROVIDER` straight into `SmsServicePlugin` with nothing to\n * compare it against, so a typo (`twilo`) reached `makeSmsTransport`, threw\n * there, was caught, and became `LogSmsTransport` — a server that answers every\n * OTP send `status: 'sent'` and delivers nothing.\n */\nexport const SMS_TRANSPORT_PROVIDERS = ['log', 'aliyun', 'twilio'] as const;\n\n/** A provider tag `makeSmsTransport` can materialise a transport for. */\nexport type SmsProviderTag = (typeof SMS_TRANSPORT_PROVIDERS)[number];\n\n/**\n * Narrow an unknown value to a buildable provider tag. The counterpart of\n * `isEmailTransportProvider` in `@objectstack/plugin-email`, and used by the CLI\n * for the same reason: a provider that cannot deliver must be refused where the\n * operator declared it, not silently downgraded where it is materialised.\n */\nexport function isSmsTransportProvider(value: unknown): value is SmsProviderTag {\n return typeof value === 'string'\n && (SMS_TRANSPORT_PROVIDERS as readonly string[]).includes(value);\n}\n\nexport interface MakeSmsTransportOptions {\n provider: SmsProviderTag;\n /** Provider-specific credentials/options (see the transport option types). */\n options?: Record<string, unknown>;\n logger?: { info: (msg: string, meta?: any) => void };\n}\n\n/**\n * Build an ISmsTransport from a provider tag + opts. Used by\n * SmsServicePlugin to materialise the transport selected by config /\n * the `sms` settings namespace.\n *\n * Throws when a non-`log` provider is missing required credentials.\n */\nexport function makeSmsTransport(opts: MakeSmsTransportOptions): ISmsTransport {\n const { provider, options = {}, logger } = opts;\n switch (provider) {\n case 'log':\n return new LogSmsTransport(logger);\n case 'aliyun':\n return new AliyunSmsTransport(options as any);\n case 'twilio':\n return new TwilioSmsTransport(options as any);\n default:\n throw new Error(`makeSmsTransport: unknown provider '${provider}'`);\n }\n}\n"],"mappings":"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","names":["import_rate_limit_storage"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/sms-daily-quota.ts","../src/sms-service.ts","../src/sms-plugin.ts","../src/transports/aliyun.ts","../src/transports/twilio.ts","../src/transports/index.ts"],"mappings":"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","names":["import_rate_limit_storage"]}
|
package/dist/index.mjs
CHANGED
|
@@ -407,13 +407,20 @@ var SmsServicePlugin = class {
|
|
|
407
407
|
* `ObjectKernel.bootstrap`), so declaring the edge is what puts the bind
|
|
408
408
|
* ahead of the read.
|
|
409
409
|
*
|
|
410
|
-
* `sms` is the entry this card was filed about: it
|
|
411
|
-
* `PLATFORM_ALWAYS_ON_CAPABILITIES`, one past the
|
|
412
|
-
* before this declaration its correct
|
|
413
|
-
* held by nothing at all. In the window
|
|
414
|
-
* the manifest defaults — a `log` provider
|
|
415
|
-
* a default cost ceiling — while the
|
|
416
|
-
* in `sys_setting`.
|
|
410
|
+
* `sms` is the entry this card was filed about: it was added at index 6 of
|
|
411
|
+
* `PLATFORM_ALWAYS_ON_CAPABILITIES`, one past the `slice(0, 6)` prefix that
|
|
412
|
+
* was pinned there at the time, so before this declaration its correct
|
|
413
|
+
* position relative to `settings` was held by nothing at all. In the window
|
|
414
|
+
* `getNamespace('sms')` answers from the manifest defaults — a `log` provider
|
|
415
|
+
* that reports every OTP "sent" and a default cost ceiling — while the
|
|
416
|
+
* operator's saved credentials sit unread in `sys_setting`.
|
|
417
|
+
*
|
|
418
|
+
* That slice is retired (#11046): the slate pin states the rule instead —
|
|
419
|
+
* every always-on entry that is not a bind target (`queue`/`job`/`cache`/
|
|
420
|
+
* `settings`) is mounted after all of them — so `sms` is now held BY the pin
|
|
421
|
+
* rather than sitting one past it, and so is whatever is added next. That
|
|
422
|
+
* covers slate ORDER only; this declaration is still what orders the plugins,
|
|
423
|
+
* and the pin test named below is what keeps it honest.
|
|
417
424
|
*
|
|
418
425
|
* SOFT, not hard: a kernel with no settings service must still boot this
|
|
419
426
|
* plugin (the transport is buildable from options alone). ADR-0049 —
|
|
@@ -503,11 +510,13 @@ var SmsServicePlugin = class {
|
|
|
503
510
|
try {
|
|
504
511
|
const payload = await settings.getNamespace("sms");
|
|
505
512
|
const values = {};
|
|
513
|
+
const sources = {};
|
|
506
514
|
for (const [k, v] of Object.entries(payload.values)) {
|
|
507
515
|
values[k] = v?.value;
|
|
516
|
+
if (v?.source) sources[k] = String(v.source);
|
|
508
517
|
}
|
|
509
518
|
this.dailyQuota?.setQuota(values.daily_quota);
|
|
510
|
-
if (!this.options.transport) this.applySmsSettings(values, ctx);
|
|
519
|
+
if (!this.options.transport) this.applySmsSettings(values, sources, ctx);
|
|
511
520
|
} catch (err) {
|
|
512
521
|
ctx.logger.warn("SmsServicePlugin: failed to apply sms settings: " + (err?.message ?? err));
|
|
513
522
|
}
|
|
@@ -570,7 +579,7 @@ var SmsServicePlugin = class {
|
|
|
570
579
|
* on the running SmsService. Incomplete credentials keep the previous
|
|
571
580
|
* transport (with a warning) so a half-saved form can't break delivery.
|
|
572
581
|
*/
|
|
573
|
-
applySmsSettings(values, ctx) {
|
|
582
|
+
applySmsSettings(values, sources, ctx) {
|
|
574
583
|
if (!this.service) return;
|
|
575
584
|
const resolved = providerFromSettings(values);
|
|
576
585
|
if (resolved.missing) {
|
|
@@ -580,7 +589,7 @@ var SmsServicePlugin = class {
|
|
|
580
589
|
return;
|
|
581
590
|
}
|
|
582
591
|
if (resolved.provider === "log") {
|
|
583
|
-
if (values.provider === "log") {
|
|
592
|
+
if (values.provider === "log" && (sources.provider ?? "default") !== "default") {
|
|
584
593
|
this.service.setTransport(new LogSmsTransport(ctx.logger), false);
|
|
585
594
|
ctx.logger.info("SmsServicePlugin: sms settings applied (provider=log; SMS will NOT be sent).");
|
|
586
595
|
}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sms-daily-quota.ts","../src/sms-service.ts","../src/sms-plugin.ts","../src/transports/aliyun.ts","../src/transports/twilio.ts","../src/transports/index.ts"],"sourcesContent":["// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Global daily SMS send quota — the COST TOTAL gate (#2814).\n *\n * ## What this adds that the per-number guard cannot\n *\n * #2780 gave the OTP endpoints a per-NUMBER budget (60s cooldown + 5 sends per\n * number per hour, `plugin-auth/src/otp-send-guard.ts`). That bounds what one\n * phone number costs. It does not bound what the DEPLOYMENT costs: an attacker\n * rotating through ten thousand distinct numbers keeps every one of them inside\n * its own budget while the daily bill has no ceiling at all — classic SMS\n * pumping / toll fraud. And the per-number guard sits in better-auth's\n * `hooks.before`, so it only ever sees the auth endpoints: `notify(channels:\n * ['sms'])` and the invitation path walk straight past it.\n *\n * This gate is therefore counted at the ONE place every outbound message\n * already funnels through — `SmsService.send()` — so OTP, invitations and the\n * messaging `sms` channel are all charged against the same budget, whatever\n * door they came in by.\n *\n * ## Where it counts (#4790's answer, reused verbatim)\n *\n * A budget is only worth what its store is worth: counted per process, a\n * declared \"2000 per day\" is really 2000×N across N nodes, and nothing says so\n * (ADR-0049 — declared ≠ enforced). So this counts through the SAME resolution\n * the auth counters use — `createLazyCounterStore` over the kernel `cache`\n * service, resolved at COUNTING time (not at plugin init, the #4772 trap),\n * with a bounded per-process fallback that announces itself. The counting\n * algorithm is `incrementFixedWindow`, imported rather than re-implemented:\n * this repo has exactly one fixed-window counter and #4790 said plainly that a\n * third copy is not wanted.\n *\n * ## The window is a UTC calendar day, twice over\n *\n * \"Daily quota\" means the calendar day, not \"24h from the first send\", so the\n * counter key carries the UTC date (`sms-daily-sends:2026-08-06`) AND the\n * window is opened with exactly the seconds remaining until the next UTC\n * midnight. Either mechanism alone would roll the budget over; together they\n * cannot disagree — a clock skew that mis-sizes the TTL still lands on a fresh\n * key at 00:00Z, and a store that ignores TTLs still starts a new key.\n *\n * ## Admission-time counting, and fail-open\n *\n * A unit is consumed when a send is ADMITTED, before the transport runs —\n * exactly like `OtpSendGuard.checkAndRecord` and\n * `createLazyCacheRateLimitStorage.consume`, both of which take the\n * post-increment count and compare it to the cap. Two consequences, stated\n * rather than discovered later: a transport failure still spends a unit (the\n * conservative direction for a COST ceiling, and the alternative is a second\n * store round-trip on every send), and attempts refused by this gate keep\n * incrementing the day's counter, so the number in the log line is \"attempts\n * today\", not \"messages delivered today\".\n *\n * Every store interaction is fail-OPEN: a cache outage must not take phone\n * sign-in down with it (#2814 requirement 4). A degraded gate is announced once\n * and then admits.\n *\n * ## What is NOT here\n *\n * The per-tenant dimension (`daily_quota_per_tenant`, keyed by\n * `organizationId`) is deliberately absent: `SendSmsInput`\n * (`@objectstack/spec/contracts/sms-service.ts`) carries no tenant identifier,\n * and inventing a second, service-local spelling of one would be exactly the\n * shadow contract AGENTS.md Prime Directive #12 forbids. See the issue thread\n * on #2814 — the tenant identifier belongs on the spec contract or nowhere.\n */\n\nimport {\n InProcessCounterStore,\n incrementFixedWindow,\n type CounterStore,\n} from '@objectstack/plugin-auth/rate-limit-storage';\n\n/**\n * The error code a quota-refused send answers with, as the `CODE: message`\n * prefix `SmsService` already uses for `VALIDATION_FAILED`.\n *\n * Deliberately the same code the per-number guard raises in `plugin-auth`\n * (`APIError('TOO_MANY_REQUESTS')`), because #2814 asks the two walls to be\n * indistinguishable from outside: an attacker must not be able to tell which\n * budget they hit, and a legitimate caller needs no more than \"not now\".\n * The message carries NO remaining-quota detail for the same reason.\n */\nexport const SMS_QUOTA_EXCEEDED_CODE = 'TOO_MANY_REQUESTS';\n\n/** The refusal text handed back on `SendSmsResult.error`. Contains no counts. */\nexport const SMS_QUOTA_EXCEEDED_ERROR = `${SMS_QUOTA_EXCEEDED_CODE}: daily SMS quota exhausted`;\n\n/** Key prefix for the day counter. Carries a date only — never a recipient. */\nconst KEY_PREFIX = 'sms-daily-sends:';\n\n/** Fraction of the quota at which the approaching-ceiling WARN fires. */\nconst NEAR_LIMIT_RATIO = 0.8;\n\ntype LoggerLike = {\n info?(msg: string, meta?: Record<string, unknown>): void;\n warn?(msg: string, meta?: Record<string, unknown>): void;\n};\n\nexport interface SmsDailyQuotaOptions {\n /**\n * Resolve the store the day counter lives in — called on EVERY check, so a\n * shared cache registered after this gate was constructed is picked up on the\n * next send rather than never (#4772/#4790). `SmsServicePlugin` supplies\n * `createLazyCounterStore(...)`; omitted ⇒ a per-process store, silently\n * (the gate constructed standalone, e.g. in tests).\n */\n resolveStore?: () => Promise<CounterStore>;\n /** Diagnostics sink. NEVER receives a message body or a recipient. */\n logger?: LoggerLike;\n /** Clock override for tests. */\n now?: () => number;\n}\n\n/** Outcome of one admission check. */\nexport interface SmsDailyQuotaDecision {\n /** Whether the send may proceed. */\n ok: boolean;\n /**\n * Attempts counted for the current UTC day AFTER this one, when the counter\n * was actually consulted. Absent when the gate is off or degraded.\n */\n count?: number;\n /** The enforced ceiling this decision was measured against (`0` ⇒ off). */\n quota?: number;\n}\n\n/** `YYYY-MM-DD` in UTC — the day the counter key is scoped to. */\nexport function utcDayStamp(now: number): string {\n return new Date(now).toISOString().slice(0, 10);\n}\n\n/**\n * Seconds from `now` to the next UTC midnight, at least 1. This is the window\n * `incrementFixedWindow` opens on the day's first send, so the counter expires\n * with the day it belongs to instead of 24h after whenever it started.\n */\nexport function secondsUntilNextUtcMidnight(now: number): number {\n const d = new Date(now);\n const next = Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate() + 1);\n return Math.max(1, Math.ceil((next - now) / 1000));\n}\n\n/**\n * Result of reading an authored quota value: the ceiling actually enforced,\n * plus the offending input when one had to be discarded.\n */\nexport interface NormalizedDailyQuota {\n /** Enforced ceiling. `0` means unlimited. Always a non-negative integer. */\n limit: number;\n /** Set when the authored value was unusable and `0` was substituted. */\n rejected?: string;\n}\n\n/**\n * Clamp an authored `sms.daily_quota` into the value actually enforced.\n *\n * **This lives on the CONSUMER side on purpose (#5932).** It was written while\n * `min` was inert — `SettingsService.validatePatch` declared five value\n * constraints and read only `pattern`, so a `min: 0` filtered nothing and\n * negative, fractional and outright non-numeric values all reached a reader\n * intact. #5932 has since closed the producer half: the declared window is\n * enforced on the save path and on the `OS_*` env path, so `daily_quota: -1`\n * is now refused at `PUT /api/settings/sms` with a `min_value` FieldError.\n *\n * The clamp stays, and not out of sentiment — three of its inputs are still\n * genuinely reachable, so removing it would re-open a live hole rather than\n * delete a dead one:\n *\n * - **Non-numeric values** (`true`, `'unlimited'`, `{ n: 5 }`). The window\n * check deliberately does not judge a value's SHAPE — that is `invalid_type`,\n * a different constraint with a different owner — so these still arrive.\n * - **Fractional counts.** `100.5` is inside `min: 0` and always was; flooring\n * is this reader's rule, not the manifest's.\n * - **Historical rows.** The save-path check runs under the TOUCH gate, so a\n * value stored before the gate existed survives until someone re-writes that\n * key — deliberately, so a workspace carrying drift is not locked out of its\n * own settings page.\n *\n * What changed is the failure mode this defends against, not whether it is\n * needed: a bad value is now refused where it is authored (loudly, at the\n * producer, per ADR-0049), and this clamp is what keeps a value that predates\n * or sidesteps that gate from becoming behaviour.\n *\n * The rules, and why each is the safe direction for a paid channel:\n *\n * - **absent / empty string** → `0` (unlimited), quietly. That is \"the operator\n * has not configured a ceiling\", which is the shipped default, not an error.\n * - **finite number ≥ 0** → `Math.floor(v)`. A fractional message count is\n * rounded DOWN, the stricter direction for a cost ceiling, and is not worth a\n * diagnostic — `100.5` unambiguously means \"at most 100 messages\".\n * - **negative, NaN, ±Infinity, or a non-numeric type** → `0` (unlimited) plus\n * a named rejection the caller logs LOUDLY.\n *\n * That last rule is the one worth arguing. Two other readings exist and both\n * are worse here. Refusing to send at all turns one typo in a settings form\n * into a total outage of phone sign-in — the precise failure #2814 requirement\n * 4 rules out (\"配额闸不能把登录拖下水\"), and the same reasoning `SettingsService`\n * applies when it ignores a rejected `OS_*` override rather than acting on it.\n * Substituting some other default invents a ceiling nobody declared and hides\n * the typo behind plausible behaviour (#5152's lesson, where a typo'd\n * `invite_only` read as `auto` left an operator believing a wall was up).\n * Ignoring the value and SAYING SO leaves the deployment exactly where it was\n * before the bad edit, with a line naming the value to fix.\n */\nexport function normalizeDailyQuota(raw: unknown): NormalizedDailyQuota {\n if (raw === undefined || raw === null) return { limit: 0 };\n if (typeof raw === 'string') {\n const trimmed = raw.trim();\n if (trimmed.length === 0) return { limit: 0 };\n const parsed = Number(trimmed);\n if (Number.isFinite(parsed) && parsed >= 0) return { limit: Math.floor(parsed) };\n return { limit: 0, rejected: trimmed };\n }\n if (typeof raw === 'number') {\n if (Number.isFinite(raw) && raw >= 0) return { limit: Math.floor(raw) };\n return { limit: 0, rejected: String(raw) };\n }\n return { limit: 0, rejected: typeof raw === 'object' ? JSON.stringify(raw) : String(raw) };\n}\n\n/**\n * The global daily send ceiling, counted once per admitted send.\n *\n * Constructed by `SmsServicePlugin` and handed to `SmsService`; `setQuota` is\n * called on every `sms` settings change so an admin edit takes effect without a\n * restart (same live-swap contract as the transport).\n */\nexport class SmsDailyQuota {\n private limit = 0;\n private readonly resolveStore: () => Promise<CounterStore>;\n private readonly logger?: LoggerLike;\n private readonly now: () => number;\n\n /**\n * Per-process fallback used when no resolver was supplied at all (the gate\n * constructed standalone). The SAME bounded store the auth counters degrade\n * to — one fallback implementation across the repo, not a second one that can\n * drift (#4790).\n */\n private readonly fallback = new InProcessCounterStore();\n\n /** The last authored value reported as unusable — deduped, per value. */\n private reportedRejection?: string;\n /** UTC day stamp the approaching-ceiling WARN has already fired for. */\n private nearLimitWarnedFor?: string;\n /** UTC day stamp the ceiling-reached WARN has already fired for. */\n private exceededWarnedFor?: string;\n /** Store-outage WARN is once per process — see `checkAndRecord`. */\n private degradedWarned = false;\n\n constructor(options: SmsDailyQuotaOptions = {}) {\n this.logger = options.logger;\n this.now = options.now ?? Date.now;\n this.resolveStore = options.resolveStore ?? (async () => this.fallback);\n }\n\n /**\n * Apply an authored `sms.daily_quota`. Anything unusable degrades to\n * \"unlimited\" and is reported once per distinct offending value — see\n * {@link normalizeDailyQuota} for why that is the safe direction.\n */\n setQuota(raw: unknown): void {\n const { limit, rejected } = normalizeDailyQuota(raw);\n this.limit = limit;\n if (rejected !== undefined && rejected !== this.reportedRejection) {\n this.reportedRejection = rejected;\n this.logger?.warn?.(\n `[sms] daily_quota value '${rejected}' is not a usable message count — the daily SMS quota is ` +\n 'NOT enforced until it is corrected. Use a non-negative whole number, or 0 for \"no limit\".',\n );\n }\n }\n\n /** The ceiling actually in force (`0` ⇒ unlimited). @internal test seam */\n get enforcedQuota(): number {\n return this.limit;\n }\n\n /**\n * Charge one send against today's budget and answer whether it may proceed.\n *\n * Never throws: a store outage fails OPEN (announced once per process), for\n * the reason in the file header — an SMS cost ceiling that can block sign-in\n * is a worse problem than the one it solves.\n */\n async checkAndRecord(): Promise<SmsDailyQuotaDecision> {\n if (this.limit <= 0) return { ok: true, quota: 0 };\n const now = this.now();\n const day = utcDayStamp(now);\n try {\n const store = await this.resolveStore();\n const { count } = await incrementFixedWindow(\n store,\n KEY_PREFIX + day,\n secondsUntilNextUtcMidnight(now),\n now,\n );\n\n if (count > this.limit) {\n if (this.exceededWarnedFor !== day) {\n this.exceededWarnedFor = day;\n this.logger?.warn?.(\n `[sms] daily SMS quota reached — further sends are refused until 00:00 UTC.`,\n { day, count, quota: this.limit },\n );\n }\n return { ok: false, count, quota: this.limit };\n }\n\n if (count >= Math.ceil(this.limit * NEAR_LIMIT_RATIO) && this.nearLimitWarnedFor !== day) {\n this.nearLimitWarnedFor = day;\n this.logger?.warn?.(\n `[sms] daily SMS quota is ${Math.round(NEAR_LIMIT_RATIO * 100)}% consumed.`,\n { day, count, quota: this.limit },\n );\n }\n return { ok: true, count, quota: this.limit };\n } catch (err) {\n if (!this.degradedWarned) {\n this.degradedWarned = true;\n this.logger?.warn?.(\n '[sms] daily SMS quota counter is unreadable (' +\n String((err as Error)?.message ?? err) +\n ') — the gate is FAILING OPEN and today\\'s spend is unbounded until the counter store recovers. ' +\n 'Sign-in is deliberately not taken down with it (#2814).',\n );\n }\n return { ok: true };\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type {\n ISmsService,\n ISmsTransport,\n NormalizedSmsMessage,\n SendSmsInput,\n SendSmsResult,\n SmsTransportSendResult,\n} from '@objectstack/spec/contracts';\nimport { SMS_QUOTA_EXCEEDED_ERROR, type SmsDailyQuota } from './sms-daily-quota.js';\n\n/**\n * Normalize + validate a recipient phone number. Accepts E.164 and common\n * human formats (spaces / dashes / dots / parens are stripped). Returns\n * `undefined` when the result doesn't look like a phone number.\n *\n * Same shape rule as plugin-auth's `normalizePhoneNumber` — 6-15 digits\n * with an optional leading `+` (kept local: the two packages must not\n * depend on each other).\n */\nexport function normalizeSmsRecipient(raw: string): string | undefined {\n const stripped = String(raw ?? '').replace(/[\\s\\-().]/g, '');\n return /^\\+?[0-9]{6,15}$/.test(stripped) ? stripped : undefined;\n}\n\n/**\n * Mask a phone number for log lines: keep the prefix (country-code-ish) and\n * the last two digits, hide the middle. `+8613812345678` → `+8613******78`.\n * SMS logging policy: masked recipient + status ONLY — never the body\n * (OTP codes travel in it; see the ISmsService contract header).\n */\nexport function maskPhoneNumber(phone: string): string {\n const p = String(phone ?? '');\n if (p.length <= 6) return `${p.slice(0, 2)}****`;\n return `${p.slice(0, 5)}${'*'.repeat(Math.max(2, p.length - 7))}${p.slice(-2)}`;\n}\n\n/**\n * Development transport — never actually sends. Logs the masked recipient\n * (and, OUTSIDE production only, the message body so local OTP flows are\n * testable) and returns a synthetic message id.\n *\n * The production-body suppression is a hard rule from #2780: OTP codes must\n * never land in logs. In dev the body IS the delivery — same pattern as the\n * auth magic-link / invitation URLs, which are printed in dev only.\n */\nexport class LogSmsTransport implements ISmsTransport {\n private counter = 0;\n constructor(private readonly logger?: { info: (msg: string, meta?: any) => void }) {}\n async send(message: NormalizedSmsMessage): Promise<SmsTransportSendResult> {\n const messageId = `dev-sms-${Date.now()}-${++this.counter}`;\n const dev = (globalThis as any)?.process?.env?.NODE_ENV !== 'production';\n this.logger?.info(\n `[LogSmsTransport] would send SMS to ${maskPhoneNumber(message.to)}` +\n (dev ? ` — body: ${message.body}` : ' (body suppressed outside dev)'),\n { messageId },\n );\n return { messageId, response: 'logged' };\n }\n}\n\nexport interface SmsServiceOptions {\n transport: ISmsTransport;\n /**\n * Whether `transport` is a real provider (Aliyun / Twilio / injected).\n * `false` = development log fallback; surfaced via `isConfigured()` so\n * consumers can gate SMS-dependent features in production.\n */\n configured: boolean;\n /** Retry attempts on transport throw. Default 0 (no retry). */\n retries?: number;\n /** Logger for diagnostic output. NEVER receives message bodies. */\n logger?: {\n info: (msg: string, meta?: any) => void;\n warn: (msg: string, meta?: any) => void;\n };\n /**\n * The deployment-wide daily send ceiling (#2814). Charged once per admitted\n * send, HERE rather than at the auth endpoints, so OTP, invitations and the\n * messaging `sms` channel are all counted against the one budget — see\n * `sms-daily-quota.ts`. Omitted ⇒ no total-cost gate (the pre-#2814\n * behaviour).\n */\n dailyQuota?: SmsDailyQuota;\n}\n\n/**\n * Concrete ISmsService implementation.\n *\n * Flow: validate + normalize input → transport.send() (with optional\n * retry) → SendSmsResult. Deliberately NO persistence and NO body logging —\n * see the contract header in `@objectstack/spec/contracts/sms-service.ts`.\n */\nexport class SmsService implements ISmsService {\n constructor(public options: SmsServiceOptions) {\n if (!options.transport) throw new Error('SmsService: transport is required');\n }\n\n /**\n * Hot-swap the underlying transport (settings namespace changed). The\n * `configured` flag travels with the transport.\n */\n setTransport(transport: ISmsTransport, configured: boolean): void {\n this.options.transport = transport;\n this.options.configured = configured;\n }\n\n isConfigured(): boolean {\n return this.options.configured;\n }\n\n async send(input: SendSmsInput): Promise<SendSmsResult> {\n const to = normalizeSmsRecipient(input?.to ?? '');\n if (!to) {\n throw new Error(`VALIDATION_FAILED: '${maskPhoneNumber(String(input?.to ?? ''))}' is not a valid phone number`);\n }\n const body = String(input?.body ?? '').trim();\n if (!body && !input?.templateId && !input?.templateParams) {\n throw new Error('VALIDATION_FAILED: body (or templateId/templateParams) is required');\n }\n\n const normalized: NormalizedSmsMessage = {\n to,\n body,\n ...(input.templateId ? { templateId: input.templateId } : {}),\n ...(input.templateParams ? { templateParams: input.templateParams } : {}),\n };\n\n const id = `sms-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n\n // #2814 — the deployment's daily cost ceiling, charged after the input is\n // known to be a real send (a malformed recipient never spent anything, so\n // it must not spend a unit either) and before the transport, which is the\n // only ordering that actually caps spend. Refusal is reported as a failed\n // send carrying the SAME `TOO_MANY_REQUESTS` code the per-number guard\n // raises, with no remaining-quota detail — outside, the two walls are\n // indistinguishable on purpose.\n //\n // Measured caveat (#6039): on the auth OTP path that code does NOT reach\n // the HTTP caller today. `AuthManager.deliverPhoneOtp` rethrows a plain\n // `Error`, and better-call answers 500 for anything that is not an\n // `APIError` — so the endpoint returns 500 while the per-number guard on\n // the same endpoint returns 429. Closing that needs a change inside\n // plugin-auth, which is why it is filed rather than papered over here.\n if (this.options.dailyQuota) {\n const decision = await this.options.dailyQuota.checkAndRecord();\n if (!decision.ok) {\n this.options.logger?.warn?.(\n `[SmsService] send to ${maskPhoneNumber(to)} refused: daily quota exhausted`,\n );\n return { id, status: 'failed', error: SMS_QUOTA_EXCEEDED_ERROR };\n }\n }\n const maxAttempts = (this.options.retries ?? 0) + 1;\n let lastError: unknown;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const result = await this.options.transport.send(normalized);\n this.options.logger?.info(\n `[SmsService] sent to ${maskPhoneNumber(to)} (messageId=${result.messageId})`,\n );\n return { id, status: 'sent', messageId: result.messageId };\n } catch (err) {\n lastError = err;\n if (attempt < maxAttempts) {\n await new Promise((r) => setTimeout(r, Math.min(2000, 100 * 2 ** (attempt - 1))));\n }\n }\n }\n const errMessage = String((lastError as Error)?.message ?? lastError ?? 'send failed').slice(0, 500);\n this.options.logger?.warn(\n `[SmsService] send to ${maskPhoneNumber(to)} failed: ${errMessage}`,\n );\n return { id, status: 'failed', error: errMessage };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport type { ISmsTransport } from '@objectstack/spec/contracts';\nimport { createLazyCounterStore, type CounterStore } from '@objectstack/plugin-auth/rate-limit-storage';\nimport { SmsService, LogSmsTransport, maskPhoneNumber, normalizeSmsRecipient } from './sms-service.js';\nimport { SmsDailyQuota } from './sms-daily-quota.js';\nimport { makeSmsTransport, type SmsProviderTag } from './transports/index.js';\n\n/**\n * Plugin configuration. Mirrors EmailServicePluginOptions: a directly\n * injected transport wins, then `provider` + credentials, then the\n * development `LogSmsTransport` fallback (no real send).\n */\nexport interface SmsServicePluginOptions {\n /** Pluggable delivery transport. Overrides `provider`/credentials. */\n transport?: ISmsTransport;\n /** Provider tag — `'log' | 'aliyun' | 'twilio'`. Default `'log'`. */\n provider?: SmsProviderTag;\n /** Provider-specific credentials/options (see transport option types). */\n providerOptions?: Record<string, unknown>;\n /** Retry attempts on transport throw. Default 0. */\n retries?: number;\n}\n\n/** Translate an `sms` settings-namespace snapshot into transport inputs. */\nfunction providerFromSettings(values: Record<string, unknown>): {\n provider: SmsProviderTag;\n options: Record<string, unknown>;\n missing?: string;\n} {\n const provider = String(values.provider ?? 'log') as SmsProviderTag;\n const str = (k: string): string | undefined => {\n const v = values[k];\n return typeof v === 'string' && v.trim().length > 0 ? v.trim() : undefined;\n };\n if (provider === 'aliyun') {\n const accessKeyId = str('aliyun_access_key_id');\n const accessKeySecret = str('aliyun_access_key_secret');\n const signName = str('aliyun_sign_name');\n if (!accessKeyId || !accessKeySecret || !signName) {\n return { provider, options: {}, missing: 'aliyun_access_key_id / aliyun_access_key_secret / aliyun_sign_name' };\n }\n return {\n provider,\n options: {\n accessKeyId,\n accessKeySecret,\n signName,\n ...(str('aliyun_template_code') ? { defaultTemplateCode: str('aliyun_template_code') } : {}),\n },\n };\n }\n if (provider === 'twilio') {\n const accountSid = str('twilio_account_sid');\n const authToken = str('twilio_auth_token');\n const from = str('twilio_from_number');\n const messagingServiceSid = str('twilio_messaging_service_sid');\n if (!accountSid || !authToken || (!from && !messagingServiceSid)) {\n return { provider, options: {}, missing: 'twilio_account_sid / twilio_auth_token / twilio_from_number (or messaging service SID)' };\n }\n return {\n provider,\n options: {\n accountSid,\n authToken,\n ...(from ? { from } : {}),\n ...(messagingServiceSid ? { messagingServiceSid } : {}),\n },\n };\n }\n return { provider: 'log', options: {} };\n}\n\n/**\n * SmsServicePlugin — registers the `sms` service (#2780).\n *\n * Lifecycle:\n * - `init`: build transport (injected → provider+credentials →\n * LogSmsTransport fallback); register the SmsService so dependents\n * (auth OTP, the messaging `sms` channel) can resolve it.\n * - `start` (kernel:ready): bind the `sms` settings namespace so the\n * admin UI can live-swap the provider without a restart, and register\n * the `sms/test` action. Env-locked keys (OS_SMS_*) still win at the\n * settings-resolver level.\n *\n * Deliberately NO persistence objects: SMS bodies carry OTP codes — see the\n * ISmsService contract header.\n */\nexport class SmsServicePlugin implements Plugin {\n name = 'com.objectstack.service.sms';\n /**\n * Services init() registers on every path (ADR-0116, #4131) — lets the\n * kernel name this plugin when a consumer requires one before it inits.\n */\n providesServices = ['sms'];\n /**\n * Order-if-present on the settings service (ADR-0116, #10250).\n *\n * `start()` registers a `kernel:ready` hook that reads the `sms` namespace —\n * provider credentials AND the daily cost ceiling. `SettingsServicePlugin`\n * binds its data engine from ITS `kernel:ready` hook, registered in ITS\n * `start()`, so the plugin that starts first registers the earlier hook and\n * the earlier hook runs first. Start order is the topological order over this\n * declaration (`resolvePluginOrder`, used for BOTH phases in\n * `ObjectKernel.bootstrap`), so declaring the edge is what puts the bind\n * ahead of the read.\n *\n * `sms` is the entry this card was filed about: it sits at index 6 of\n * `PLATFORM_ALWAYS_ON_CAPABILITIES`, one past the pinned `slice(0, 6)`, so\n * before this declaration its correct position relative to `settings` was\n * held by nothing at all. In the window `getNamespace('sms')` answers from\n * the manifest defaults — a `log` provider that reports every OTP \"sent\" and\n * a default cost ceiling — while the operator's saved credentials sit unread\n * in `sys_setting`.\n *\n * SOFT, not hard: a kernel with no settings service must still boot this\n * plugin (the transport is buildable from options alone). ADR-0049 —\n * declared is enforced: `serve-settings-ordering.pin.test.ts` boots a kernel\n * with the readers registered BEFORE settings and proves the order moves.\n */\n optionalDependencies = ['com.objectstack.service.settings'];\n version = '1.0.0';\n type = 'standard' as const;\n\n private readonly options: SmsServicePluginOptions;\n private service?: SmsService;\n private dailyQuota?: SmsDailyQuota;\n\n constructor(options: SmsServicePluginOptions = {}) {\n this.options = options;\n }\n\n /**\n * Build the daily cost gate (#2814) over the kernel `cache` service.\n *\n * `resolveCache` is copied in shape from `AuthPlugin.init()` on purpose, for\n * the two reasons stated there: the `cache` service is registered ASYNC (so\n * `getService` throws for it and `getServiceAsync` is the only accessor that\n * works), and resolution has to happen when a counter is CONSUMED rather than\n * at init, or a deployment that registers its cache after this plugin freezes\n * a \"no shared store\" answer for the life of the process (#4772). The\n * degraded case is announced by `createLazyCounterStore` itself, named for\n * this subject.\n */\n private buildDailyQuota(ctx: PluginContext): SmsDailyQuota {\n const resolveCache = async (): Promise<CounterStore | undefined> => {\n let cache: any;\n try {\n cache = await (ctx as { getServiceAsync?: (n: string) => Promise<unknown> })\n .getServiceAsync?.('cache');\n } catch {\n return undefined;\n }\n if (cache && typeof cache.get === 'function' && typeof cache.set === 'function') return cache;\n return undefined;\n };\n return new SmsDailyQuota({\n resolveStore: createLazyCounterStore({\n resolveCache,\n logger: ctx.logger,\n logPrefix: '[sms]',\n subject: 'daily SMS send quota (#2814)',\n degradedImpact:\n 'The ceiling is still enforced, but PER NODE: an N-node deployment can spend up to N× the ' +\n 'configured number of PAID SMS per day, which is exactly the total-cost hole this gate exists to close',\n }),\n logger: ctx.logger,\n });\n }\n\n private resolveInitialTransport(ctx: PluginContext): { transport: ISmsTransport; configured: boolean } {\n if (this.options.transport) return { transport: this.options.transport, configured: true };\n const provider = this.options.provider ?? 'log';\n if (provider === 'log') return { transport: new LogSmsTransport(ctx.logger), configured: false };\n try {\n return {\n transport: makeSmsTransport({ provider, options: this.options.providerOptions, logger: ctx.logger }),\n configured: true,\n };\n } catch (err: any) {\n // Incomplete constructor credentials must not take the kernel down —\n // fall back to the dev transport; the settings bind (kernel:ready)\n // can still swap in a working provider.\n ctx.logger.warn(\n `SmsServicePlugin: provider='${provider}' selected but transport build failed (${err?.message ?? err}) — falling back to LogSmsTransport.`,\n );\n return { transport: new LogSmsTransport(ctx.logger), configured: false };\n }\n }\n\n async init(ctx: PluginContext): Promise<void> {\n const { transport, configured } = this.resolveInitialTransport(ctx);\n if (!configured) {\n ctx.logger.info('SmsServicePlugin: no provider configured — using LogSmsTransport (SMS will NOT be sent)');\n } else {\n ctx.logger.info(`SmsServicePlugin: using '${this.options.provider ?? 'custom'}' provider`);\n }\n this.dailyQuota = this.buildDailyQuota(ctx);\n this.service = new SmsService({\n transport,\n configured,\n retries: this.options.retries,\n logger: ctx.logger,\n dailyQuota: this.dailyQuota,\n });\n ctx.registerService('sms', this.service);\n ctx.logger.info('SmsServicePlugin: sms service registered');\n }\n\n async start(ctx: PluginContext): Promise<void> {\n ctx.hook('kernel:ready', async () => {\n if (!this.service) return;\n try {\n const settings = ctx.getService<any>('settings');\n if (!settings || typeof settings.getNamespace !== 'function') return;\n\n const applySettings = async () => {\n try {\n const payload = await settings.getNamespace('sms');\n const values: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(payload.values as Record<string, any>)) {\n values[k] = v?.value;\n }\n // #2814 — the daily cost ceiling binds for EVERY composition,\n // including a host-injected transport: \"how much may this\n // deployment spend today\" is an operator policy about the\n // deployment, not a property of whichever transport delivers.\n // Read by VALUE, never by `ResolvedSettingValue.source` — an\n // env-locked `OS_SMS_DAILY_QUOTA` and an admin-saved row are the\n // same instruction to this reader (#5536).\n this.dailyQuota?.setQuota(values.daily_quota);\n // A host-injected transport, by contrast, IS authoritative — the\n // settings form only manages the provider-tag path.\n if (!this.options.transport) this.applySmsSettings(values, ctx);\n } catch (err: any) {\n ctx.logger.warn('SmsServicePlugin: failed to apply sms settings: ' + (err?.message ?? err));\n }\n };\n await applySettings();\n if (typeof settings.subscribe === 'function') {\n settings.subscribe('sms', () => { void applySettings(); });\n ctx.logger.info('SmsServicePlugin: bound to settings:changed for namespace=sms');\n }\n\n // `sms/test` action — validate the (possibly unsaved) form values by\n // sending a real test message through a one-shot transport, mirroring\n // the `mail/test` handler in EmailServicePlugin. Still skipped when the\n // host injected its own transport: the form's provider fields describe\n // nothing that composition uses, so testing them would be theatre.\n if (!this.options.transport && typeof settings.registerAction === 'function') {\n const svc = this.service;\n settings.registerAction('sms', 'test', async ({ values, payload, ctx: actionCtx }: any) => {\n const overrides = (payload && typeof payload === 'object' && payload.values && typeof payload.values === 'object')\n ? payload.values\n : (payload ?? {});\n const merged: Record<string, unknown> = { ...(values ?? {}), ...overrides };\n const rawTo = (actionCtx?.body?.to as string | undefined) ?? (payload?.to as string | undefined);\n const to = rawTo ? normalizeSmsRecipient(rawTo) : undefined;\n if (!to) {\n return { ok: false, severity: 'error', message: 'Provide a valid \"to\" phone number (E.164 recommended).' };\n }\n\n const resolved = providerFromSettings(merged);\n if (resolved.missing) {\n return { ok: false, severity: 'error', message: `${resolved.provider}: missing ${resolved.missing}.` };\n }\n\n let target: SmsService = svc;\n if (resolved.provider !== 'log') {\n try {\n const transport = makeSmsTransport({ provider: resolved.provider, options: resolved.options, logger: ctx.logger });\n target = new SmsService({ transport, configured: true, logger: ctx.logger });\n } catch (err: any) {\n return { ok: false, severity: 'error', message: `Failed to build ${resolved.provider} transport: ${err?.message ?? String(err)}` };\n }\n }\n\n try {\n const result = await target.send({\n to,\n body: 'ObjectStack SMS test message.',\n templateParams: { content: 'ObjectStack SMS test message.' },\n });\n if (result.status === 'failed') {\n return { ok: false, severity: 'error', message: result.error ?? 'Send failed.' };\n }\n return {\n ok: true,\n severity: 'info',\n message: `Sent test SMS to ${maskPhoneNumber(to)} via ${resolved.provider} (id=${result.messageId ?? result.id}).`,\n };\n } catch (err: any) {\n return { ok: false, severity: 'error', message: err?.message ?? String(err) };\n }\n });\n }\n } catch {\n // settings service not registered — constructor opts remain authoritative.\n }\n });\n }\n\n /**\n * Translate the `sms` settings snapshot into a transport and hot-swap it\n * on the running SmsService. Incomplete credentials keep the previous\n * transport (with a warning) so a half-saved form can't break delivery.\n */\n private applySmsSettings(values: Record<string, unknown>, ctx: PluginContext): void {\n if (!this.service) return;\n const resolved = providerFromSettings(values);\n if (resolved.missing) {\n ctx.logger.warn(\n `SmsServicePlugin: provider='${resolved.provider}' selected but ${resolved.missing} is empty — transport NOT rebuilt.`,\n );\n return;\n }\n if (resolved.provider === 'log') {\n // Downgrade to the dev transport only when the operator explicitly\n // selected `log`; an unset namespace keeps the constructor opts.\n if (values.provider === 'log') {\n this.service.setTransport(new LogSmsTransport(ctx.logger), false);\n ctx.logger.info('SmsServicePlugin: sms settings applied (provider=log; SMS will NOT be sent).');\n }\n return;\n }\n try {\n const transport = makeSmsTransport({ provider: resolved.provider, options: resolved.options, logger: ctx.logger });\n this.service.setTransport(transport, true);\n ctx.logger.info(`SmsServicePlugin: transport rebuilt from settings (provider=${resolved.provider}).`);\n } catch (err: any) {\n ctx.logger.warn('SmsServicePlugin: failed to rebuild transport: ' + (err?.message ?? err));\n }\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport { createHash, createHmac, randomUUID } from 'node:crypto';\nimport type { ISmsTransport, NormalizedSmsMessage, SmsTransportSendResult } from '@objectstack/spec/contracts';\n\nexport interface AliyunSmsTransportOptions {\n accessKeyId: string;\n accessKeySecret: string;\n /** 短信签名 SignName — the registered sender signature, e.g. `阿里云短信测试`. */\n signName: string;\n /**\n * Default 模板 TemplateCode used when the input carries no `templateId`\n * (Aliyun only delivers pre-registered templates — free-form bodies are\n * refused by the API). A catch-all template with a single `${content}`\n * variable makes generic notification sends possible.\n */\n defaultTemplateCode?: string;\n /** API endpoint host. Default `dysmsapi.aliyuncs.com`. */\n endpoint?: string;\n /** Injectable fetch for tests. */\n fetchImpl?: typeof fetch;\n}\n\nconst API_VERSION = '2017-05-25';\nconst ALGORITHM = 'ACS3-HMAC-SHA256';\n\nconst sha256Hex = (s: string): string => createHash('sha256').update(s, 'utf8').digest('hex');\nconst hmac256Hex = (key: string, s: string): string => createHmac('sha256', key).update(s, 'utf8').digest('hex');\n\n/** RFC 3986 percent-encoding (Aliyun requires `%20`, `%2A`, `%7E` handling). */\nconst encode = (s: string): string =>\n encodeURIComponent(s)\n .replace(/\\+/g, '%20')\n .replace(/\\*/g, '%2A')\n .replace(/%7E/g, '~');\n\n/**\n * Aliyun SMS (dysmsapi `SendSms`) transport, signed with the current\n * ACS3-HMAC-SHA256 scheme — plain `fetch` + `node:crypto`, no vendor SDK.\n *\n * Aliyun is template-only: the transport sends `templateId` (falling back to\n * the configured default TemplateCode) with `templateParams` (falling back to\n * `{ content: body }` for the catch-all-template pattern). The rendered\n * `body` itself is never transmitted outside `TemplateParam`.\n */\nexport class AliyunSmsTransport implements ISmsTransport {\n private readonly endpoint: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(private readonly options: AliyunSmsTransportOptions) {\n if (!options.accessKeyId || !options.accessKeySecret) {\n throw new Error('AliyunSmsTransport: accessKeyId and accessKeySecret are required');\n }\n if (!options.signName) {\n throw new Error('AliyunSmsTransport: signName is required');\n }\n this.endpoint = options.endpoint ?? 'dysmsapi.aliyuncs.com';\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n async send(message: NormalizedSmsMessage): Promise<SmsTransportSendResult> {\n const templateCode = message.templateId ?? this.options.defaultTemplateCode;\n if (!templateCode) {\n throw new Error(\n 'AliyunSmsTransport: Aliyun requires a template — pass templateId or configure a default template code',\n );\n }\n const templateParam = JSON.stringify(message.templateParams ?? { content: message.body });\n\n const query: Record<string, string> = {\n PhoneNumbers: message.to,\n SignName: this.options.signName,\n TemplateCode: templateCode,\n TemplateParam: templateParam,\n };\n const canonicalQuery = Object.keys(query)\n .sort()\n .map((k) => `${encode(k)}=${encode(query[k])}`)\n .join('&');\n\n const bodyHash = sha256Hex(''); // POST with all parameters in the query string\n const headers: Record<string, string> = {\n host: this.endpoint,\n 'x-acs-action': 'SendSms',\n 'x-acs-content-sha256': bodyHash,\n 'x-acs-date': new Date().toISOString().replace(/\\.\\d{3}Z$/, 'Z'),\n 'x-acs-signature-nonce': randomUUID(),\n 'x-acs-version': API_VERSION,\n };\n const signedHeaderNames = Object.keys(headers).sort();\n const canonicalHeaders = signedHeaderNames.map((k) => `${k}:${headers[k].trim()}\\n`).join('');\n const signedHeaders = signedHeaderNames.join(';');\n\n const canonicalRequest = ['POST', '/', canonicalQuery, canonicalHeaders, signedHeaders, bodyHash].join('\\n');\n const stringToSign = `${ALGORITHM}\\n${sha256Hex(canonicalRequest)}`;\n const signature = hmac256Hex(this.options.accessKeySecret, stringToSign);\n\n const response = await this.fetchImpl(`https://${this.endpoint}/?${canonicalQuery}`, {\n method: 'POST',\n headers: {\n ...headers,\n Authorization: `${ALGORITHM} Credential=${this.options.accessKeyId},SignedHeaders=${signedHeaders},Signature=${signature}`,\n },\n });\n\n let payload: any = {};\n try { payload = await response.json(); } catch { /* non-JSON error body */ }\n if (!response.ok || payload?.Code !== 'OK') {\n const code = payload?.Code ?? `HTTP_${response.status}`;\n const detail = payload?.Message ?? response.statusText ?? 'request failed';\n throw new Error(`Aliyun SendSms failed (${code}): ${detail}`);\n }\n return { messageId: String(payload.BizId ?? payload.RequestId ?? ''), response: payload.RequestId };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ISmsTransport, NormalizedSmsMessage, SmsTransportSendResult } from '@objectstack/spec/contracts';\n\nexport interface TwilioSmsTransportOptions {\n accountSid: string;\n authToken: string;\n /** Sender number (E.164). One of `from` / `messagingServiceSid` is required. */\n from?: string;\n /** Twilio Messaging Service SID (alternative to a fixed `from` number). */\n messagingServiceSid?: string;\n /** API base URL override (tests). Default `https://api.twilio.com`. */\n baseUrl?: string;\n /** Injectable fetch for tests. */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Twilio Programmable Messaging transport — a single `POST\n * /2010-04-01/Accounts/{sid}/Messages.json` with HTTP Basic auth. Plain\n * `fetch`, no vendor SDK. Free-form: delivers `body` verbatim.\n */\nexport class TwilioSmsTransport implements ISmsTransport {\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof fetch;\n\n constructor(private readonly options: TwilioSmsTransportOptions) {\n if (!options.accountSid || !options.authToken) {\n throw new Error('TwilioSmsTransport: accountSid and authToken are required');\n }\n if (!options.from && !options.messagingServiceSid) {\n throw new Error('TwilioSmsTransport: one of from / messagingServiceSid is required');\n }\n this.baseUrl = (options.baseUrl ?? 'https://api.twilio.com').replace(/\\/$/, '');\n this.fetchImpl = options.fetchImpl ?? fetch;\n }\n\n async send(message: NormalizedSmsMessage): Promise<SmsTransportSendResult> {\n const form = new URLSearchParams({\n To: message.to,\n Body: message.body,\n ...(this.options.messagingServiceSid\n ? { MessagingServiceSid: this.options.messagingServiceSid }\n : { From: this.options.from as string }),\n });\n const auth = Buffer.from(`${this.options.accountSid}:${this.options.authToken}`).toString('base64');\n const response = await this.fetchImpl(\n `${this.baseUrl}/2010-04-01/Accounts/${encodeURIComponent(this.options.accountSid)}/Messages.json`,\n {\n method: 'POST',\n headers: {\n Authorization: `Basic ${auth}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: form.toString(),\n },\n );\n\n let payload: any = {};\n try { payload = await response.json(); } catch { /* non-JSON error body */ }\n if (!response.ok) {\n const code = payload?.code ?? `HTTP_${response.status}`;\n const detail = payload?.message ?? response.statusText ?? 'request failed';\n throw new Error(`Twilio send failed (${code}): ${detail}`);\n }\n return { messageId: String(payload.sid ?? ''), response: payload.status };\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\nimport type { ISmsTransport } from '@objectstack/spec/contracts';\nimport { LogSmsTransport } from '../sms-service.js';\nimport { AliyunSmsTransport } from './aliyun.js';\nimport { TwilioSmsTransport } from './twilio.js';\n\nexport { AliyunSmsTransport, type AliyunSmsTransportOptions } from './aliyun.js';\nexport { TwilioSmsTransport, type TwilioSmsTransportOptions } from './twilio.js';\n\n/**\n * The provider vocabulary — every tag `makeSmsTransport` below can build, and\n * nothing else. It is the **one** literal: the `SmsProviderTag` type is derived\n * from it, the `switch` is exhaustive over it, and callers that have to judge an\n * operator-supplied provider string (the CLI's `sms` capability arm, #5713) read\n * it from here rather than restating the list.\n *\n * Two literals describing one vocabulary is how the mail settings dropdown and\n * the mail transports drifted apart (#5094) — `sendgrid`/`ses` were offered with\n * no transport behind them while `resend` had a working transport nobody could\n * pick. The SMS boot path had the same shape from the other side: `os serve`\n * passed `OS_SMS_PROVIDER` straight into `SmsServicePlugin` with nothing to\n * compare it against, so a typo (`twilo`) reached `makeSmsTransport`, threw\n * there, was caught, and became `LogSmsTransport` — a server that answers every\n * OTP send `status: 'sent'` and delivers nothing.\n */\nexport const SMS_TRANSPORT_PROVIDERS = ['log', 'aliyun', 'twilio'] as const;\n\n/** A provider tag `makeSmsTransport` can materialise a transport for. */\nexport type SmsProviderTag = (typeof SMS_TRANSPORT_PROVIDERS)[number];\n\n/**\n * Narrow an unknown value to a buildable provider tag. The counterpart of\n * `isEmailTransportProvider` in `@objectstack/plugin-email`, and used by the CLI\n * for the same reason: a provider that cannot deliver must be refused where the\n * operator declared it, not silently downgraded where it is materialised.\n */\nexport function isSmsTransportProvider(value: unknown): value is SmsProviderTag {\n return typeof value === 'string'\n && (SMS_TRANSPORT_PROVIDERS as readonly string[]).includes(value);\n}\n\nexport interface MakeSmsTransportOptions {\n provider: SmsProviderTag;\n /** Provider-specific credentials/options (see the transport option types). */\n options?: Record<string, unknown>;\n logger?: { info: (msg: string, meta?: any) => void };\n}\n\n/**\n * Build an ISmsTransport from a provider tag + opts. Used by\n * SmsServicePlugin to materialise the transport selected by config /\n * the `sms` settings namespace.\n *\n * Throws when a non-`log` provider is missing required credentials.\n */\nexport function makeSmsTransport(opts: MakeSmsTransportOptions): ISmsTransport {\n const { provider, options = {}, logger } = opts;\n switch (provider) {\n case 'log':\n return new LogSmsTransport(logger);\n case 'aliyun':\n return new AliyunSmsTransport(options as any);\n case 'twilio':\n return new TwilioSmsTransport(options as any);\n default:\n throw new Error(`makeSmsTransport: unknown provider '${provider}'`);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/sms-daily-quota.ts","../src/sms-service.ts","../src/sms-plugin.ts","../src/transports/aliyun.ts","../src/transports/twilio.ts","../src/transports/index.ts"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/service-sms",
|
|
3
|
-
"version": "17.
|
|
3
|
+
"version": "17.4.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "SMS service for ObjectStack — ISmsService + transport-pluggable outbound delivery (Aliyun / Twilio / log).",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@objectstack/core": "17.
|
|
17
|
-
"@objectstack/
|
|
18
|
-
"@objectstack/
|
|
16
|
+
"@objectstack/core": "17.4.0",
|
|
17
|
+
"@objectstack/plugin-auth": "17.4.0",
|
|
18
|
+
"@objectstack/spec": "17.4.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/node": "^26.2.0",
|
|
22
22
|
"typescript": "^6.0.3",
|
|
23
23
|
"vitest": "^4.1.10",
|
|
24
|
-
"@objectstack/service-settings": "17.
|
|
24
|
+
"@objectstack/service-settings": "17.4.0"
|
|
25
25
|
},
|
|
26
26
|
"keywords": [
|
|
27
27
|
"objectstack",
|
|
@@ -30,14 +30,21 @@
|
|
|
30
30
|
"aliyun",
|
|
31
31
|
"twilio"
|
|
32
32
|
],
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/objectstack-ai/objectstack.git",
|
|
36
|
+
"directory": "packages/services/service-sms"
|
|
37
|
+
},
|
|
33
38
|
"files": [
|
|
34
39
|
"dist",
|
|
35
40
|
"README.md",
|
|
36
41
|
"CHANGELOG.md"
|
|
37
42
|
],
|
|
38
43
|
"scripts": {
|
|
39
|
-
"build": "tsup --config ../../../tsup.config.ts",
|
|
44
|
+
"build": "tsup --config ../../../tsup.config.ts && node ../../../scripts/check-dts-emitted.mjs",
|
|
45
|
+
"check:test-typecheck": "tsx ../../../scripts/check-test-typecheck.mts --self-test && tsx ../../../scripts/check-test-typecheck.mts --package packages/services/service-sms --project tsconfig.test.json",
|
|
46
|
+
"gen:test-typecheck-debt": "tsx ../../../scripts/check-test-typecheck.mts --update --package packages/services/service-sms --project tsconfig.test.json",
|
|
40
47
|
"test": "vitest run --passWithNoTests",
|
|
41
|
-
"typecheck": "tsc --noEmit"
|
|
48
|
+
"typecheck": "tsc --noEmit && pnpm check:test-typecheck"
|
|
42
49
|
}
|
|
43
50
|
}
|