mppx 0.6.18 → 0.6.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/Challenge.d.ts +2 -2
  3. package/dist/Challenge.d.ts.map +1 -1
  4. package/dist/Challenge.js +1 -1
  5. package/dist/Challenge.js.map +1 -1
  6. package/dist/Method.d.ts +34 -0
  7. package/dist/Method.d.ts.map +1 -1
  8. package/dist/Method.js +3 -1
  9. package/dist/Method.js.map +1 -1
  10. package/dist/Receipt.d.ts +1 -0
  11. package/dist/Receipt.d.ts.map +1 -1
  12. package/dist/Receipt.js +2 -0
  13. package/dist/Receipt.js.map +1 -1
  14. package/dist/client/Methods.d.ts +1 -0
  15. package/dist/client/Methods.d.ts.map +1 -1
  16. package/dist/client/Methods.js +1 -0
  17. package/dist/client/Methods.js.map +1 -1
  18. package/dist/middlewares/elysia.d.ts.map +1 -1
  19. package/dist/middlewares/elysia.js +14 -0
  20. package/dist/middlewares/elysia.js.map +1 -1
  21. package/dist/middlewares/express.d.ts.map +1 -1
  22. package/dist/middlewares/express.js +1 -2
  23. package/dist/middlewares/express.js.map +1 -1
  24. package/dist/middlewares/hono.d.ts.map +1 -1
  25. package/dist/middlewares/hono.js +14 -0
  26. package/dist/middlewares/hono.js.map +1 -1
  27. package/dist/middlewares/nextjs.d.ts.map +1 -1
  28. package/dist/middlewares/nextjs.js +14 -0
  29. package/dist/middlewares/nextjs.js.map +1 -1
  30. package/dist/proxy/Proxy.d.ts.map +1 -1
  31. package/dist/proxy/Proxy.js +2 -2
  32. package/dist/proxy/Proxy.js.map +1 -1
  33. package/dist/proxy/Service.d.ts.map +1 -1
  34. package/dist/proxy/Service.js +1 -1
  35. package/dist/proxy/Service.js.map +1 -1
  36. package/dist/server/Mppx.d.ts +15 -3
  37. package/dist/server/Mppx.d.ts.map +1 -1
  38. package/dist/server/Mppx.js +190 -40
  39. package/dist/server/Mppx.js.map +1 -1
  40. package/dist/stripe/server/internal/html.gen.d.ts +1 -1
  41. package/dist/stripe/server/internal/html.gen.d.ts.map +1 -1
  42. package/dist/stripe/server/internal/html.gen.js +1 -1
  43. package/dist/stripe/server/internal/html.gen.js.map +1 -1
  44. package/dist/tempo/Methods.d.ts +96 -0
  45. package/dist/tempo/Methods.d.ts.map +1 -1
  46. package/dist/tempo/Methods.js +97 -0
  47. package/dist/tempo/Methods.js.map +1 -1
  48. package/dist/tempo/client/Methods.d.ts +3 -0
  49. package/dist/tempo/client/Methods.d.ts.map +1 -1
  50. package/dist/tempo/client/Methods.js +3 -0
  51. package/dist/tempo/client/Methods.js.map +1 -1
  52. package/dist/tempo/client/Subscription.d.ts +114 -0
  53. package/dist/tempo/client/Subscription.d.ts.map +1 -0
  54. package/dist/tempo/client/Subscription.js +100 -0
  55. package/dist/tempo/client/Subscription.js.map +1 -0
  56. package/dist/tempo/client/index.d.ts +1 -0
  57. package/dist/tempo/client/index.d.ts.map +1 -1
  58. package/dist/tempo/client/index.js +1 -0
  59. package/dist/tempo/client/index.js.map +1 -1
  60. package/dist/tempo/index.d.ts +1 -0
  61. package/dist/tempo/index.d.ts.map +1 -1
  62. package/dist/tempo/index.js +1 -0
  63. package/dist/tempo/index.js.map +1 -1
  64. package/dist/tempo/server/Charge.js +2 -2
  65. package/dist/tempo/server/Charge.js.map +1 -1
  66. package/dist/tempo/server/Methods.d.ts +5 -0
  67. package/dist/tempo/server/Methods.d.ts.map +1 -1
  68. package/dist/tempo/server/Methods.js +5 -0
  69. package/dist/tempo/server/Methods.js.map +1 -1
  70. package/dist/tempo/server/Subscription.d.ts +221 -0
  71. package/dist/tempo/server/Subscription.d.ts.map +1 -0
  72. package/dist/tempo/server/Subscription.js +637 -0
  73. package/dist/tempo/server/Subscription.js.map +1 -0
  74. package/dist/tempo/server/index.d.ts +1 -0
  75. package/dist/tempo/server/index.d.ts.map +1 -1
  76. package/dist/tempo/server/index.js +1 -0
  77. package/dist/tempo/server/index.js.map +1 -1
  78. package/dist/tempo/server/internal/html.gen.d.ts +1 -1
  79. package/dist/tempo/server/internal/html.gen.d.ts.map +1 -1
  80. package/dist/tempo/server/internal/html.gen.js +1 -1
  81. package/dist/tempo/server/internal/html.gen.js.map +1 -1
  82. package/dist/tempo/session/Chain.d.ts.map +1 -1
  83. package/dist/tempo/session/Chain.js +3 -4
  84. package/dist/tempo/session/Chain.js.map +1 -1
  85. package/dist/tempo/subscription/KeyAuthorization.d.ts +282 -0
  86. package/dist/tempo/subscription/KeyAuthorization.d.ts.map +1 -0
  87. package/dist/tempo/subscription/KeyAuthorization.js +297 -0
  88. package/dist/tempo/subscription/KeyAuthorization.js.map +1 -0
  89. package/dist/tempo/subscription/Receipt.d.ts +10 -0
  90. package/dist/tempo/subscription/Receipt.d.ts.map +1 -0
  91. package/dist/tempo/subscription/Receipt.js +16 -0
  92. package/dist/tempo/subscription/Receipt.js.map +1 -0
  93. package/dist/tempo/subscription/Store.d.ts +99 -0
  94. package/dist/tempo/subscription/Store.d.ts.map +1 -0
  95. package/dist/tempo/subscription/Store.js +292 -0
  96. package/dist/tempo/subscription/Store.js.map +1 -0
  97. package/dist/tempo/subscription/Types.d.ts +65 -0
  98. package/dist/tempo/subscription/Types.d.ts.map +1 -0
  99. package/dist/tempo/subscription/Types.js +2 -0
  100. package/dist/tempo/subscription/Types.js.map +1 -0
  101. package/dist/tempo/subscription/index.d.ts +6 -0
  102. package/dist/tempo/subscription/index.d.ts.map +1 -0
  103. package/dist/tempo/subscription/index.js +4 -0
  104. package/dist/tempo/subscription/index.js.map +1 -0
  105. package/dist/zod.d.ts +7 -0
  106. package/dist/zod.d.ts.map +1 -1
  107. package/dist/zod.js +18 -0
  108. package/dist/zod.js.map +1 -1
  109. package/package.json +3 -3
  110. package/src/Challenge.test.ts +13 -0
  111. package/src/Challenge.ts +3 -3
  112. package/src/Method.ts +46 -1
  113. package/src/Receipt.ts +2 -0
  114. package/src/client/Methods.ts +1 -0
  115. package/src/middlewares/elysia.test.ts +31 -1
  116. package/src/middlewares/elysia.ts +13 -0
  117. package/src/middlewares/express.ts +1 -5
  118. package/src/middlewares/hono.test.ts +30 -1
  119. package/src/middlewares/hono.ts +13 -0
  120. package/src/middlewares/nextjs.test.ts +28 -1
  121. package/src/middlewares/nextjs.ts +13 -0
  122. package/src/proxy/Proxy.ts +2 -5
  123. package/src/proxy/Service.test.ts +34 -0
  124. package/src/proxy/Service.ts +7 -0
  125. package/src/server/Mppx.authorize.test.ts +210 -0
  126. package/src/server/Mppx.test-d.ts +23 -1
  127. package/src/server/Mppx.test.ts +73 -3
  128. package/src/server/Mppx.ts +291 -58
  129. package/src/stripe/server/internal/html/package.json +1 -1
  130. package/src/stripe/server/internal/html.gen.ts +1 -1
  131. package/src/tempo/Methods.test.ts +131 -0
  132. package/src/tempo/Methods.ts +136 -0
  133. package/src/tempo/Subscription.integration.test.ts +591 -0
  134. package/src/tempo/client/Methods.ts +3 -0
  135. package/src/tempo/client/Subscription.test.ts +131 -0
  136. package/src/tempo/client/Subscription.ts +155 -0
  137. package/src/tempo/client/index.ts +1 -0
  138. package/src/tempo/index.ts +1 -0
  139. package/src/tempo/server/Charge.ts +2 -2
  140. package/src/tempo/server/Methods.ts +5 -0
  141. package/src/tempo/server/Subscription.test.ts +1410 -0
  142. package/src/tempo/server/Subscription.ts +1014 -0
  143. package/src/tempo/server/index.ts +1 -0
  144. package/src/tempo/server/internal/html/package.json +1 -1
  145. package/src/tempo/server/internal/html.gen.ts +1 -1
  146. package/src/tempo/session/Chain.ts +3 -5
  147. package/src/tempo/subscription/KeyAuthorization.test.ts +204 -0
  148. package/src/tempo/subscription/KeyAuthorization.ts +394 -0
  149. package/src/tempo/subscription/Receipt.ts +28 -0
  150. package/src/tempo/subscription/Store.test.ts +554 -0
  151. package/src/tempo/subscription/Store.ts +431 -0
  152. package/src/tempo/subscription/Types.ts +68 -0
  153. package/src/tempo/subscription/index.ts +23 -0
  154. package/src/zod.test.ts +23 -1
  155. package/src/zod.ts +24 -0
@@ -0,0 +1,292 @@
1
+ import { Secp256k1 } from 'ox';
2
+ import { Account as TempoAccount } from 'viem/tempo';
3
+ const defaultRecordPrefix = 'tempo:subscription:record:';
4
+ const defaultKeyPrefix = 'tempo:subscription:key:';
5
+ const defaultActivationPrefix = 'tempo:subscription:activation:';
6
+ const defaultAccessKeyPrefix = 'tempo:subscription:access-key:';
7
+ const defaultCredentialPrefix = 'tempo:subscription:credential:';
8
+ const defaultActivationTimeoutMs = 15 * 60 * 1_000;
9
+ const defaultRenewalTimeoutMs = 15 * 60 * 1_000;
10
+ /** Wraps a generic key-value {@link Store.Store} with subscription-specific accessors. */
11
+ export function fromStore(store, options) {
12
+ const { accessKeyPrefix = defaultAccessKeyPrefix, activationPrefix = defaultActivationPrefix, activationTimeoutMs = defaultActivationTimeoutMs, credentialPrefix = defaultCredentialPrefix, keyPrefix = defaultKeyPrefix, recordPrefix = defaultRecordPrefix, renewalTimeoutMs = defaultRenewalTimeoutMs, } = options ?? {};
13
+ function recordKey(subscriptionId) {
14
+ return `${recordPrefix}${subscriptionId}`;
15
+ }
16
+ function activationKey(key) {
17
+ return `${activationPrefix}${key}`;
18
+ }
19
+ function credentialKey(challengeId) {
20
+ return `${credentialPrefix}${challengeId}`;
21
+ }
22
+ function accessKeyKey(key) {
23
+ return `${accessKeyPrefix}${key}`;
24
+ }
25
+ function lookupRecordKey(key) {
26
+ return `${keyPrefix}${key}`;
27
+ }
28
+ async function getByLookupKey(key) {
29
+ const subscriptionId = (await store.get(lookupRecordKey(key)));
30
+ if (!subscriptionId)
31
+ return null;
32
+ return (await store.get(recordKey(subscriptionId)));
33
+ }
34
+ async function clearRenewalState(subscriptionId, periodIndex, attempt) {
35
+ await store.update(recordKey(subscriptionId), (current) => {
36
+ const subscription = current;
37
+ if (!subscription ||
38
+ subscription.inFlightPeriod !== periodIndex ||
39
+ subscription.inFlightAttempt !== attempt) {
40
+ return { op: 'noop', result: undefined };
41
+ }
42
+ return {
43
+ op: 'set',
44
+ value: clearRenewal(subscription),
45
+ result: undefined,
46
+ };
47
+ });
48
+ }
49
+ async function clearActivationState(lookupKey, challengeId) {
50
+ await store.update(activationKey(lookupKey), (current) => {
51
+ const marker = current;
52
+ if (marker?.challengeId !== challengeId)
53
+ return { op: 'noop', result: undefined };
54
+ return { op: 'delete', result: undefined };
55
+ });
56
+ }
57
+ async function ownsActivation(lookupKey, challengeId) {
58
+ const marker = (await store.get(activationKey(lookupKey)));
59
+ return marker?.challengeId === challengeId;
60
+ }
61
+ return {
62
+ async activate({ challengeId, create, isReusable, lookupKey }) {
63
+ const claimed = await store.update(credentialKey(challengeId), (current) => {
64
+ if (current)
65
+ return { op: 'noop', result: false };
66
+ return {
67
+ op: 'set',
68
+ value: { claimedAt: timestamp() },
69
+ result: true,
70
+ };
71
+ });
72
+ if (!claimed)
73
+ return { status: 'replayed' };
74
+ const existing = await getByLookupKey(lookupKey);
75
+ if (existing && isReusable?.(existing)) {
76
+ return { status: 'existing', subscription: existing };
77
+ }
78
+ const started = await store.update(activationKey(lookupKey), (current) => {
79
+ const marker = current;
80
+ if (marker && !isStaleActivation(marker, activationTimeoutMs)) {
81
+ return { op: 'noop', result: { status: 'inFlight' } };
82
+ }
83
+ return {
84
+ op: 'set',
85
+ value: {
86
+ challengeId,
87
+ startedAt: timestamp(),
88
+ },
89
+ result: { status: 'started' },
90
+ };
91
+ });
92
+ if (started.status !== 'started')
93
+ return { status: 'inFlight' };
94
+ const claimedExisting = await getByLookupKey(lookupKey);
95
+ if (claimedExisting && isReusable?.(claimedExisting)) {
96
+ await clearActivationState(lookupKey, challengeId);
97
+ return { status: 'existing', subscription: claimedExisting };
98
+ }
99
+ const result = await create().catch(async (error) => {
100
+ await clearActivationState(lookupKey, challengeId);
101
+ throw error;
102
+ });
103
+ const { subscription } = result;
104
+ const committed = await store.update(activationKey(subscription.lookupKey), (current) => {
105
+ const marker = current;
106
+ if (marker?.challengeId !== challengeId)
107
+ return { op: 'noop', result: false };
108
+ return {
109
+ op: 'set',
110
+ value: {
111
+ ...marker,
112
+ committingAt: timestamp(),
113
+ startedAt: timestamp(),
114
+ },
115
+ result: true,
116
+ };
117
+ });
118
+ if (!committed) {
119
+ await store.put(recordKey(subscription.subscriptionId), {
120
+ ...subscription,
121
+ canceledAt: subscription.canceledAt ?? timestamp(),
122
+ });
123
+ return { status: 'claimMismatch' };
124
+ }
125
+ const previous = await getByLookupKey(subscription.lookupKey);
126
+ if (previous && previous.subscriptionId !== subscription.subscriptionId) {
127
+ if (!(await ownsActivation(subscription.lookupKey, challengeId))) {
128
+ return { status: 'claimMismatch' };
129
+ }
130
+ await store.put(recordKey(previous.subscriptionId), {
131
+ ...previous,
132
+ canceledAt: previous.canceledAt ?? timestamp(),
133
+ });
134
+ }
135
+ if (!(await ownsActivation(subscription.lookupKey, challengeId))) {
136
+ return { status: 'claimMismatch' };
137
+ }
138
+ await store.put(recordKey(subscription.subscriptionId), subscription);
139
+ if (!(await ownsActivation(subscription.lookupKey, challengeId))) {
140
+ return { status: 'claimMismatch' };
141
+ }
142
+ await store.put(lookupRecordKey(subscription.lookupKey), subscription.subscriptionId);
143
+ await clearActivationState(subscription.lookupKey, challengeId);
144
+ return { status: 'activated', result };
145
+ },
146
+ async get(subscriptionId) {
147
+ return (await store.get(recordKey(subscriptionId)));
148
+ },
149
+ async getAccessKey(key) {
150
+ return (await store.get(accessKeyKey(key)));
151
+ },
152
+ async getByKey(key) {
153
+ return getByLookupKey(key);
154
+ },
155
+ async getOrCreateAccessKey(key) {
156
+ const existing = (await store.get(accessKeyKey(key)));
157
+ if (existing)
158
+ return existing;
159
+ const privateKey = Secp256k1.randomPrivateKey();
160
+ const account = TempoAccount.fromSecp256k1(privateKey);
161
+ const candidate = {
162
+ accessKeyAddress: account.address.toLowerCase(),
163
+ keyType: account.keyType,
164
+ privateKey,
165
+ };
166
+ return store.update(accessKeyKey(key), (current) => {
167
+ if (current) {
168
+ return { op: 'noop', result: current };
169
+ }
170
+ return { op: 'set', value: candidate, result: candidate };
171
+ });
172
+ },
173
+ async put(record) {
174
+ await store.put(recordKey(record.subscriptionId), record);
175
+ await store.put(lookupRecordKey(record.lookupKey), record.subscriptionId);
176
+ },
177
+ async renew({ inFlightReference, periodIndex, renew, subscriptionId }) {
178
+ const attempt = createAttemptToken();
179
+ const started = await store.update(recordKey(subscriptionId), (current) => {
180
+ const subscription = current;
181
+ if (!subscription)
182
+ return { op: 'noop', result: { status: 'missing' } };
183
+ if (subscription.lastChargedPeriod >= periodIndex) {
184
+ return {
185
+ op: 'noop',
186
+ result: { status: 'charged', subscription },
187
+ };
188
+ }
189
+ if (subscription.inFlightPeriod !== undefined &&
190
+ !isStaleRenewal(subscription, renewalTimeoutMs)) {
191
+ return {
192
+ op: 'noop',
193
+ result: { status: 'inFlight', subscription },
194
+ };
195
+ }
196
+ const next = {
197
+ ...subscription,
198
+ inFlightAttempt: attempt,
199
+ inFlightPeriod: periodIndex,
200
+ inFlightReference,
201
+ inFlightStartedAt: timestamp(),
202
+ };
203
+ return {
204
+ op: 'set',
205
+ value: next,
206
+ result: { status: 'started', subscription: next },
207
+ };
208
+ });
209
+ if (started.status !== 'started')
210
+ return started;
211
+ const active = await getByLookupKey(started.subscription.lookupKey);
212
+ if (active?.subscriptionId !== subscriptionId) {
213
+ await clearRenewalState(subscriptionId, periodIndex, attempt);
214
+ return { status: 'superseded', subscription: started.subscription };
215
+ }
216
+ const result = await renew({
217
+ inFlightReference,
218
+ periodIndex,
219
+ subscription: started.subscription,
220
+ }).catch(async (error) => {
221
+ await clearRenewalState(subscriptionId, periodIndex, attempt);
222
+ throw error;
223
+ });
224
+ const activeAfterRenew = await getByLookupKey(result.subscription.lookupKey);
225
+ if (activeAfterRenew?.subscriptionId !== subscriptionId) {
226
+ await clearRenewalState(subscriptionId, periodIndex, attempt);
227
+ return { status: 'superseded', subscription: started.subscription };
228
+ }
229
+ const committed = await store.update(recordKey(subscriptionId), (current) => {
230
+ const existing = current;
231
+ if (!existing ||
232
+ existing.inFlightPeriod !== periodIndex ||
233
+ existing.inFlightAttempt !== attempt) {
234
+ return { op: 'noop', result: false };
235
+ }
236
+ const terminal = {
237
+ ...(existing.canceledAt ? { canceledAt: existing.canceledAt } : {}),
238
+ ...(existing.revokedAt ? { revokedAt: existing.revokedAt } : {}),
239
+ };
240
+ return {
241
+ op: 'set',
242
+ value: clearRenewal({
243
+ ...result.subscription,
244
+ ...terminal,
245
+ lastChargedPeriod: periodIndex,
246
+ subscriptionId,
247
+ }),
248
+ result: true,
249
+ };
250
+ });
251
+ if (!committed)
252
+ return { status: 'claimMismatch' };
253
+ const ownsLookup = await store.update(lookupRecordKey(result.subscription.lookupKey), (current) => {
254
+ if (current !== subscriptionId)
255
+ return { op: 'noop', result: false };
256
+ return { op: 'set', value: subscriptionId, result: true };
257
+ });
258
+ if (!ownsLookup)
259
+ return { status: 'superseded', subscription: started.subscription };
260
+ return { status: 'renewed', result };
261
+ },
262
+ };
263
+ }
264
+ function isStaleActivation(marker, timeoutMs) {
265
+ if (!Number.isFinite(timeoutMs) || timeoutMs < 0)
266
+ return false;
267
+ if ('committingAt' in marker && marker.committingAt)
268
+ return false;
269
+ const startedAt = new Date(marker.startedAt ?? '').getTime();
270
+ if (!Number.isFinite(startedAt))
271
+ return true;
272
+ return Date.now() - startedAt >= timeoutMs;
273
+ }
274
+ function isStaleRenewal(subscription, timeoutMs) {
275
+ return isStaleActivation({ startedAt: subscription.inFlightStartedAt }, timeoutMs);
276
+ }
277
+ function clearRenewal(subscription) {
278
+ return {
279
+ ...subscription,
280
+ inFlightAttempt: undefined,
281
+ inFlightPeriod: undefined,
282
+ inFlightReference: undefined,
283
+ inFlightStartedAt: undefined,
284
+ };
285
+ }
286
+ function timestamp() {
287
+ return new Date().toISOString();
288
+ }
289
+ function createAttemptToken() {
290
+ return globalThis.crypto.randomUUID();
291
+ }
292
+ //# sourceMappingURL=Store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Store.js","sourceRoot":"","sources":["../../../src/tempo/subscription/Store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import type { Address } from 'viem';
2
+ /** Tempo-supported subscription period units. The shared intent also defines `month`, but Tempo cannot represent calendar-month periods exactly. */
3
+ export type SubscriptionPeriodUnit = 'day' | 'week';
4
+ /** Access key information used to authorize recurring Tempo payments. */
5
+ export type SubscriptionAccessKey = {
6
+ accessKeyAddress: Address;
7
+ keyType: 'p256' | 'secp256k1' | 'webAuthn';
8
+ };
9
+ /** Server-owned subscription access key persisted for automatic billing. */
10
+ export type SubscriptionAccessKeyRecord = SubscriptionAccessKey & {
11
+ privateKey: `0x${string}`;
12
+ };
13
+ /** Request-scoped lookup key for the active subscription tied to a route. */
14
+ export type SubscriptionLookup = {
15
+ accessKey?: SubscriptionAccessKey | undefined;
16
+ key: string;
17
+ };
18
+ /** Persisted recurring Tempo subscription state. */
19
+ export type SubscriptionRecord = {
20
+ amount: string;
21
+ billingAnchor: string;
22
+ chainId?: number | undefined;
23
+ currency: Address | string;
24
+ externalId?: string | undefined;
25
+ accessKey?: SubscriptionAccessKey | undefined;
26
+ inFlightPeriod?: number | undefined;
27
+ /** Per-attempt ownership token for the renewal currently in progress. */
28
+ inFlightAttempt?: string | undefined;
29
+ /** Stable idempotency/reconciliation reference for a renewal currently in progress. */
30
+ inFlightReference?: string | undefined;
31
+ inFlightStartedAt?: string | undefined;
32
+ /** Signed key authorization used to activate the access key. */
33
+ keyAuthorization?: `0x${string}` | undefined;
34
+ lastChargedPeriod: number;
35
+ lookupKey: string;
36
+ /** Root account that authorized the stored subscription access key. */
37
+ payer?: {
38
+ address: Address;
39
+ chainId: number;
40
+ } | undefined;
41
+ periodCount: string;
42
+ periodUnit: SubscriptionPeriodUnit;
43
+ recipient: Address | string;
44
+ reference: string;
45
+ subscriptionExpires: string;
46
+ subscriptionId: string;
47
+ timestamp: string;
48
+ canceledAt?: string | undefined;
49
+ revokedAt?: string | undefined;
50
+ };
51
+ /** Credential payload for a Tempo subscription activation. */
52
+ export type SubscriptionCredentialPayload = {
53
+ signature: `0x${string}`;
54
+ type: 'keyAuthorization';
55
+ };
56
+ /** Receipt returned for a Tempo subscription activation or renewal. */
57
+ export type SubscriptionReceipt = {
58
+ method: 'tempo';
59
+ reference: string;
60
+ status: 'success';
61
+ subscriptionId: string;
62
+ timestamp: string;
63
+ externalId?: string | undefined;
64
+ };
65
+ //# sourceMappingURL=Types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Types.d.ts","sourceRoot":"","sources":["../../../src/tempo/subscription/Types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAEnC,oJAAoJ;AACpJ,MAAM,MAAM,sBAAsB,GAAG,KAAK,GAAG,MAAM,CAAA;AAEnD,yEAAyE;AACzE,MAAM,MAAM,qBAAqB,GAAG;IAClC,gBAAgB,EAAE,OAAO,CAAA;IACzB,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,UAAU,CAAA;CAC3C,CAAA;AAED,4EAA4E;AAC5E,MAAM,MAAM,2BAA2B,GAAG,qBAAqB,GAAG;IAChE,UAAU,EAAE,KAAK,MAAM,EAAE,CAAA;CAC1B,CAAA;AAED,6EAA6E;AAC7E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAA;IAC7C,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,oDAAoD;AACpD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAA;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,SAAS,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAA;IAC7C,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACpC,uFAAuF;IACvF,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,KAAK,MAAM,EAAE,GAAG,SAAS,CAAA;IAC5C,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,uEAAuE;IACvE,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;IACzD,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,sBAAsB,CAAA;IAClC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAA;IAC3B,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B,CAAA;AAED,8DAA8D;AAC9D,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,KAAK,MAAM,EAAE,CAAA;IACxB,IAAI,EAAE,kBAAkB,CAAA;CACzB,CAAA;AAED,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,OAAO,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,SAAS,CAAA;IACjB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAChC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Types.js","sourceRoot":"","sources":["../../../src/tempo/subscription/Types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export { createSubscriptionReceipt, fromRecord } from './Receipt.js';
2
+ export { getSubscriptionRpcAllowedCalls, getSubscriptionScopes, signSubscriptionKeyAuthorization, toSubscriptionExpiryDate, toSubscriptionExpirySeconds, toSubscriptionPeriodSeconds, transferSelector, transferWithMemoSelector, verifySubscriptionKeyAuthorization, } from './KeyAuthorization.js';
3
+ export { fromStore } from './Store.js';
4
+ export type { ActivateResult, RenewResult, SubscriptionStore } from './Store.js';
5
+ export type { SubscriptionAccessKey, SubscriptionAccessKeyRecord, SubscriptionCredentialPayload, SubscriptionLookup, SubscriptionPeriodUnit, SubscriptionRecord, SubscriptionReceipt, } from './Types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tempo/subscription/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACpE,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,EACrB,gCAAgC,EAChC,wBAAwB,EACxB,2BAA2B,EAC3B,2BAA2B,EAC3B,gBAAgB,EAChB,wBAAwB,EACxB,kCAAkC,GACnC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACtC,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAChF,YAAY,EACV,qBAAqB,EACrB,2BAA2B,EAC3B,6BAA6B,EAC7B,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,YAAY,CAAA"}
@@ -0,0 +1,4 @@
1
+ export { createSubscriptionReceipt, fromRecord } from './Receipt.js';
2
+ export { getSubscriptionRpcAllowedCalls, getSubscriptionScopes, signSubscriptionKeyAuthorization, toSubscriptionExpiryDate, toSubscriptionExpirySeconds, toSubscriptionPeriodSeconds, transferSelector, transferWithMemoSelector, verifySubscriptionKeyAuthorization, } from './KeyAuthorization.js';
3
+ export { fromStore } from './Store.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tempo/subscription/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACpE,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,EACrB,gCAAgC,EAChC,wBAAwB,EACxB,2BAA2B,EAC3B,2BAA2B,EAC3B,gBAAgB,EAChB,wBAAwB,EACxB,kCAAkC,GACnC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA"}
package/dist/zod.d.ts CHANGED
@@ -1,9 +1,16 @@
1
1
  import { type ZodMiniType, z } from 'zod/mini';
2
2
  export * from 'zod/mini';
3
+ export type DatetimeInput = string | Date;
3
4
  /** Numeric string amount (e.g., "1", "1.5", "1000000"). */
4
5
  export declare function amount(): z.ZodMiniString<string>;
5
6
  /** ISO 8601 datetime string (e.g., "2025-01-06T12:00:00Z"). */
6
7
  export declare function datetime(): z.ZodMiniString<string>;
8
+ /** ISO 8601 datetime string or Date object, transformed to a Date. */
9
+ export declare function datetimeInput(message?: string): z.ZodMiniPipe<z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniCustom<Date, Date>]>, z.ZodMiniTransform<Date, DatetimeInput>>;
10
+ /** Converts an ISO 8601 datetime string or Date object to a Date. */
11
+ export declare function toDate(value: DatetimeInput): Date;
12
+ /** Serializes an ISO 8601 datetime string or Date object for wire output. */
13
+ export declare function toDatetimeString(value: DatetimeInput): string;
7
14
  /** Hex-encoded address string (0x-prefixed, 40 hex chars). */
8
15
  export declare function address(): z.ZodMiniString<string>;
9
16
  /** Hex-encoded hash string (0x-prefixed, 64 hex chars). */
package/dist/zod.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,WAAW,EAAE,CAAC,EAAE,MAAM,UAAU,CAAA;AAEpE,cAAc,UAAU,CAAA;AAExB,2DAA2D;AAC3D,wBAAgB,MAAM,4BAErB;AAED,+DAA+D;AAC/D,wBAAgB,QAAQ,4BASvB;AAED,8DAA8D;AAC9D,wBAAgB,OAAO,4BAEtB;AAED,2DAA2D;AAC3D,wBAAgB,IAAI,4BAEnB;AAED,4EAA4E;AAC5E,wBAAgB,MAAM,4BAErB;AAED,kDAAkD;AAClD,wBAAgB,SAAS,4BAExB;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,MAAM,SAAS,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAItF"}
1
+ {"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,WAAW,EAAE,CAAC,EAAE,MAAM,UAAU,CAAA;AAEpE,cAAc,UAAU,CAAA;AAExB,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,IAAI,CAAA;AAEzC,2DAA2D;AAC3D,wBAAgB,MAAM,4BAErB;AAED,+DAA+D;AAC/D,wBAAgB,QAAQ,4BASvB;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,OAAO,SAA8B,2IAOlE;AAED,qEAAqE;AACrE,wBAAgB,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAEjD;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAI7D;AAED,8DAA8D;AAC9D,wBAAgB,OAAO,4BAEtB;AAED,2DAA2D;AAC3D,wBAAgB,IAAI,4BAEnB;AAED,4EAA4E;AAC5E,wBAAgB,MAAM,4BAErB;AAED,kDAAkD;AAClD,wBAAgB,SAAS,4BAExB;AAED,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,MAAM,SAAS,WAAW,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAItF"}
package/dist/zod.js CHANGED
@@ -10,6 +10,24 @@ export function datetime() {
10
10
  .string()
11
11
  .check(z.regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/, 'Invalid ISO 8601 datetime'));
12
12
  }
13
+ /** ISO 8601 datetime string or Date object, transformed to a Date. */
14
+ export function datetimeInput(message = 'Invalid ISO 8601 datetime') {
15
+ return z
16
+ .pipe(z.union([datetime(), z.custom((value) => value instanceof Date)]), z.transform(toDate))
17
+ .check(z.refine((value) => Number.isFinite(value.getTime()), message));
18
+ }
19
+ /** Converts an ISO 8601 datetime string or Date object to a Date. */
20
+ export function toDate(value) {
21
+ return value instanceof Date ? value : new Date(value);
22
+ }
23
+ /** Serializes an ISO 8601 datetime string or Date object for wire output. */
24
+ export function toDatetimeString(value) {
25
+ if (!(value instanceof Date))
26
+ return value;
27
+ if (!Number.isFinite(value.getTime()))
28
+ return 'Invalid Date';
29
+ return value.toISOString();
30
+ }
13
31
  /** Hex-encoded address string (0x-prefixed, 40 hex chars). */
14
32
  export function address() {
15
33
  return z.string().check(z.regex(/^0x[0-9a-fA-F]{40}$/, 'Invalid address'));
package/dist/zod.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"zod.js","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,CAAC,EAAE,MAAM,UAAU,CAAA;AAEpE,cAAc,UAAU,CAAA;AAExB,2DAA2D;AAC3D,MAAM,UAAU,MAAM;IACpB,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC,CAAA;AACrE,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,QAAQ;IACtB,OAAO,CAAC;SACL,MAAM,EAAE;SACR,KAAK,CACJ,CAAC,CAAC,KAAK,CACL,sEAAsE,EACtE,2BAA2B,CAC5B,CACF,CAAA;AACL,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,OAAO;IACrB,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,qBAAqB,EAAE,iBAAiB,CAAC,CAAC,CAAA;AAC5E,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,qBAAqB,EAAE,cAAc,CAAC,CAAC,CAAA;AACzE,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,MAAM;IACpB,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,6BAA6B,EAAE,gBAAgB,CAAC,CAAC,CAAA;AACnF,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC,CAAA;AAC3E,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,cAAc,CAA6B,MAAc;IACvE,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,UAAU;QACrC,OAAQ,MAAqC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAwB,CAAA;IACjF,OAAO,MAAM,CAAA;AACf,CAAC"}
1
+ {"version":3,"file":"zod.js","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,CAAC,EAAE,MAAM,UAAU,CAAA;AAEpE,cAAc,UAAU,CAAA;AAIxB,2DAA2D;AAC3D,MAAM,UAAU,MAAM;IACpB,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC,CAAA;AACrE,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,QAAQ;IACtB,OAAO,CAAC;SACL,MAAM,EAAE;SACR,KAAK,CACJ,CAAC,CAAC,KAAK,CACL,sEAAsE,EACtE,2BAA2B,CAC5B,CACF,CAAA;AACL,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,aAAa,CAAC,OAAO,GAAG,2BAA2B;IACjE,OAAO,CAAC;SACL,IAAI,CACH,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,MAAM,CAAO,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,EACvE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CACpB;SACA,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAA;AAC1E,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,MAAM,CAAC,KAAoB;IACzC,OAAO,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAA;AACxD,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,gBAAgB,CAAC,KAAoB;IACnD,IAAI,CAAC,CAAC,KAAK,YAAY,IAAI,CAAC;QAAE,OAAO,KAAK,CAAA;IAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAAE,OAAO,cAAc,CAAA;IAC5D,OAAO,KAAK,CAAC,WAAW,EAAE,CAAA;AAC5B,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,OAAO;IACrB,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,qBAAqB,EAAE,iBAAiB,CAAC,CAAC,CAAA;AAC5E,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,qBAAqB,EAAE,cAAc,CAAC,CAAC,CAAA;AACzE,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,MAAM;IACpB,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,6BAA6B,EAAE,gBAAgB,CAAC,CAAC,CAAA;AACnF,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC,CAAA;AAC3E,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,cAAc,CAA6B,MAAc;IACvE,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,UAAU;QACrC,OAAQ,MAAqC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAwB,CAAA;IACjF,OAAO,MAAM,CAAA;AACf,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mppx",
3
3
  "type": "module",
4
- "version": "0.6.18",
4
+ "version": "0.6.20",
5
5
  "main": "./dist/index.js",
6
6
  "license": "MIT",
7
7
  "files": [
@@ -124,8 +124,8 @@
124
124
  },
125
125
  "dependencies": {
126
126
  "incur": "^0.4.5",
127
- "ox": "0.14.18",
128
- "zod": "^4.3.6"
127
+ "ox": "0.14.20",
128
+ "zod": "^4.4.3"
129
129
  },
130
130
  "repository": {
131
131
  "type": "git",
@@ -53,6 +53,19 @@ describe('from', () => {
53
53
  `)
54
54
  })
55
55
 
56
+ test('behavior: accepts expires as a Date', () => {
57
+ const challenge = Challenge.from({
58
+ id: 'abc123',
59
+ realm: 'api.example.com',
60
+ method: 'tempo',
61
+ intent: 'charge',
62
+ request: { amount: '1000000' },
63
+ expires: new Date('2025-01-06T12:00:00Z'),
64
+ })
65
+
66
+ expect(challenge.expires).toBe('2025-01-06T12:00:00.000Z')
67
+ })
68
+
56
69
  // ---------------------------------------------------------------------------
57
70
  // HMAC Challenge ID Test Vectors
58
71
  //
package/src/Challenge.ts CHANGED
@@ -129,7 +129,7 @@ export function from<
129
129
  secretKey,
130
130
  } = parameters
131
131
 
132
- const expires = parameters.expires as string
132
+ const expires = parameters.expires ? z.toDatetimeString(parameters.expires) : undefined
133
133
  const opaque =
134
134
  parameters.opaque ?? (meta !== undefined ? PaymentRequest.serialize(meta) : undefined)
135
135
  const id = secretKey
@@ -173,7 +173,7 @@ export declare namespace from {
173
173
  /** Optional digest of the request body. */
174
174
  digest?: string | undefined
175
175
  /** Optional expiration timestamp (ISO 8601). */
176
- expires?: string | undefined
176
+ expires?: z.DatetimeInput | undefined
177
177
  /** Intent type (e.g., "charge", "session"). */
178
178
  intent: string
179
179
  /** Optional server-defined correlation data (serialized as `opaque` on the challenge). Flat string-to-string map; clients MUST NOT modify. */
@@ -266,7 +266,7 @@ export declare namespace fromMethod {
266
266
  /** Optional digest of the request body. */
267
267
  digest?: string | undefined
268
268
  /** Optional expiration timestamp (ISO 8601). */
269
- expires?: string | undefined
269
+ expires?: z.DatetimeInput | undefined
270
270
  /** Optional server-defined correlation data (serialized as `opaque` on the challenge). Flat string-to-string map; clients MUST NOT modify. */
271
271
  meta?: Record<string, string> | undefined
272
272
  /** Server realm (e.g., hostname). */
package/src/Method.ts CHANGED
@@ -130,10 +130,12 @@ export type Server<
130
130
  defaults extends ExactPartial<z.input<method['schema']['request']>> = {},
131
131
  transportOverride = undefined,
132
132
  > = method & {
133
+ authorize?: AuthorizeFn<method> | undefined
133
134
  defaults?: defaults | undefined
134
135
  html?: Html.Options | undefined
135
136
  request?: RequestFn<method> | undefined
136
137
  respond?: RespondFn<method> | undefined
138
+ stableBinding?: StableBindingFn<method> | undefined
137
139
  transport?: transportOverride | undefined
138
140
  verify: VerifyFn<method>
139
141
  }
@@ -155,6 +157,45 @@ export type RequestFn<method extends Method> = (
155
157
  options: RequestContext<method>,
156
158
  ) => MaybePromise<z.input<method['schema']['request']>>
157
159
 
160
+ /**
161
+ * Optional authorization hook for a server-side method.
162
+ *
163
+ * Called after request normalization but before the 402 challenge path. This lets
164
+ * a server grant access based on existing application state (for example, an
165
+ * active subscription) without requiring a fresh `Payment` credential.
166
+ *
167
+ * **HTTP-only.** The `input` parameter is a Fetch `Request`; non-HTTP transports
168
+ * do not invoke this hook.
169
+ *
170
+ * Transports that require credential context for `withReceipt()` should return a
171
+ * `response` from this hook so adapters can short-circuit protected handlers.
172
+ */
173
+ export type AuthorizeFn<method extends Method> = (parameters: {
174
+ challenge: Challenge.Challenge<
175
+ z.output<method['schema']['request']>,
176
+ method['intent'],
177
+ method['name']
178
+ >
179
+ input: globalThis.Request
180
+ request: z.output<method['schema']['request']>
181
+ }) => MaybePromise<AuthorizeResult | undefined>
182
+
183
+ /** Successful result returned from an {@link AuthorizeFn}. */
184
+ export type AuthorizeResult = {
185
+ receipt: Receipt.Receipt
186
+ response?: globalThis.Response | undefined
187
+ }
188
+
189
+ /**
190
+ * Produces the stable request fields used to bind credentials to a route.
191
+ *
192
+ * Methods can override this to opt into additional request fields beyond the
193
+ * default amount/currency/recipient binding used by generic methods.
194
+ */
195
+ export type StableBindingFn<method extends Method> = (
196
+ request: z.output<method['schema']['request']>,
197
+ ) => Record<string, unknown>
198
+
158
199
  /** Verification function for a single method. */
159
200
  export type VerifyFn<method extends Method> = (
160
201
  parameters: VerifyContext<method>,
@@ -251,13 +292,15 @@ export function toServer<
251
292
  method: method,
252
293
  options: toServer.Options<method, defaults, transportOverride>,
253
294
  ): Server<method, defaults, transportOverride> {
254
- const { defaults, html, request, respond, transport, verify } = options
295
+ const { authorize, defaults, html, request, respond, stableBinding, transport, verify } = options
255
296
  return {
256
297
  ...method,
298
+ authorize,
257
299
  defaults,
258
300
  html,
259
301
  request,
260
302
  respond,
303
+ stableBinding,
261
304
  transport,
262
305
  verify,
263
306
  } as Server<method, defaults, transportOverride>
@@ -269,10 +312,12 @@ export declare namespace toServer {
269
312
  defaults extends RequestDefaults<method> = {},
270
313
  transportOverride extends Transport.AnyTransport | undefined = undefined,
271
314
  > = {
315
+ authorize?: AuthorizeFn<method> | undefined
272
316
  defaults?: defaults | undefined
273
317
  html?: Html.Options | undefined
274
318
  request?: RequestFn<method> | undefined
275
319
  respond?: RespondFn<method> | undefined
320
+ stableBinding?: StableBindingFn<method> | undefined
276
321
  transport?: transportOverride | undefined
277
322
  verify: VerifyFn<method>
278
323
  }
package/src/Receipt.ts CHANGED
@@ -19,6 +19,8 @@ export const Schema = z.object({
19
19
  reference: z.string(),
20
20
  /** Optional external reference ID echoed from the credential payload. */
21
21
  externalId: z.optional(z.string()),
22
+ /** Optional server-issued subscription identifier for recurring payments. */
23
+ subscriptionId: z.optional(z.string()),
22
24
  /** Payment status. Always "success" — failures use 402 + Problem Details. */
23
25
  status: z.literal('success'),
24
26
  /** RFC 3339 settlement timestamp. */
@@ -1,3 +1,4 @@
1
1
  export { stripe } from '../stripe/client/index.js'
2
+ export { subscription } from '../tempo/client/Subscription.js'
2
3
  export { tempo } from '../tempo/client/index.js'
3
4
  export { session } from '../tempo/client/Session.js'