@forklaunch/core 3.2.1 → 3.3.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/bin/gateway-mock/routes/payments-context.mjs +260 -0
- package/bin/gateway-mock/routes/payments.mjs +47 -1
- package/lib/http/bindRuntimeAuth.d.ts +53 -0
- package/lib/http/bindRuntimeAuth.d.ts.map +1 -0
- package/lib/http/bindRuntimeAuth.test.d.ts +2 -0
- package/lib/http/bindRuntimeAuth.test.d.ts.map +1 -0
- package/lib/http/index.d.ts +2 -0
- package/lib/http/index.d.ts.map +1 -1
- package/lib/http/index.js +284 -76
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +282 -76
- package/lib/http/index.mjs.map +1 -1
- package/lib/http/mcpGenerator/mcpGenerator.d.ts.map +1 -1
- package/lib/http/middleware/internal/validationDiagnostic.d.ts +3 -0
- package/lib/http/middleware/internal/validationDiagnostic.d.ts.map +1 -0
- package/lib/http/middleware/request/auth.middleware.d.ts +0 -11
- package/lib/http/middleware/request/auth.middleware.d.ts.map +1 -1
- package/lib/http/middleware/request/parse.middleware.d.ts.map +1 -1
- package/lib/http/middleware/response/enrichExpressLikeSend.middleware.d.ts.map +1 -1
- package/lib/http/middleware/response/parse.middleware.d.ts.map +1 -1
- package/lib/http/openApiV3Generator/openApiV3Generator.d.ts.map +1 -1
- package/lib/http/paymentsClient.d.ts.map +1 -1
- package/lib/http/registerDelegatedSurface.d.ts +28 -0
- package/lib/http/registerDelegatedSurface.d.ts.map +1 -0
- package/lib/http/registerDelegatedSurface.test.d.ts +2 -0
- package/lib/http/registerDelegatedSurface.test.d.ts.map +1 -0
- package/lib/http/router/discriminateBody.d.ts +2 -1
- package/lib/http/router/discriminateBody.d.ts.map +1 -1
- package/lib/http/router/expressLikeRouter.d.ts.map +1 -1
- package/lib/persistence/compliantField.d.ts.map +1 -1
- package/lib/persistence/index.js +1 -6
- package/lib/persistence/index.js.map +1 -1
- package/lib/persistence/index.mjs +1 -6
- package/lib/persistence/index.mjs.map +1 -1
- package/lib/ws/asyncApiV3Generator/asyncApiV3Generator.d.ts.map +1 -1
- package/lib/ws/index.js +94 -8
- package/lib/ws/index.js.map +1 -1
- package/lib/ws/index.mjs +94 -8
- package/lib/ws/index.mjs.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
// Mirrors companion managed-apps/domain/services/payments-context.ts; tested by source conformance.
|
|
2
|
+
/** Read-only scoped protocol; never authorizes provider financial mutations. */
|
|
3
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
4
|
+
export class PaymentContextError extends Error {
|
|
5
|
+
constructor() {
|
|
6
|
+
super("Payment context is unavailable or no longer matches");
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
function deny() {
|
|
10
|
+
throw new PaymentContextError();
|
|
11
|
+
}
|
|
12
|
+
const id = (v, prefix) => typeof v === "string" &&
|
|
13
|
+
v.length <= 128 &&
|
|
14
|
+
new RegExp(`^${prefix}[A-Za-z0-9_]+$`).test(v);
|
|
15
|
+
const uuid = (v) => typeof v === "string" &&
|
|
16
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v);
|
|
17
|
+
const apiVersion = (v) => typeof v === "string" && /^\d{4}-\d{2}-\d{2}(?:\.[a-z]+)?$/.test(v);
|
|
18
|
+
/** One immutable credential/base configuration, shared safely across requests. */
|
|
19
|
+
export class PaymentsContextProtocol {
|
|
20
|
+
forward;
|
|
21
|
+
now;
|
|
22
|
+
signingKey;
|
|
23
|
+
constructor(secret, base, forward, now = Date.now) {
|
|
24
|
+
this.forward = forward;
|
|
25
|
+
this.now = now;
|
|
26
|
+
if (!secret.trim() || secret.length > 4096)
|
|
27
|
+
deny();
|
|
28
|
+
let url;
|
|
29
|
+
try {
|
|
30
|
+
url = new URL(base);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
deny();
|
|
34
|
+
}
|
|
35
|
+
if (!["http:", "https:"].includes(url.protocol) ||
|
|
36
|
+
url.username ||
|
|
37
|
+
url.password ||
|
|
38
|
+
url.search ||
|
|
39
|
+
url.hash)
|
|
40
|
+
deny();
|
|
41
|
+
const normalized = url.href.replace(/\/+$/, "");
|
|
42
|
+
this.clock();
|
|
43
|
+
this.signingKey = createHmac("sha256", secret)
|
|
44
|
+
.update(`forklaunch/payments-context/key/v1\0${normalized}`)
|
|
45
|
+
.digest();
|
|
46
|
+
}
|
|
47
|
+
clock() {
|
|
48
|
+
const value = this.now();
|
|
49
|
+
if (!Number.isSafeInteger(value) ||
|
|
50
|
+
value < 0 ||
|
|
51
|
+
value > Number.MAX_SAFE_INTEGER - 5000)
|
|
52
|
+
return deny();
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
mac(payload) {
|
|
56
|
+
return createHmac("sha256", this.signingKey)
|
|
57
|
+
.update(`forklaunch/payments-context/token/v1\0${payload}`)
|
|
58
|
+
.digest();
|
|
59
|
+
}
|
|
60
|
+
fresh(scope) {
|
|
61
|
+
const now = this.clock();
|
|
62
|
+
if (!Number.isSafeInteger(scope.issuedAt) ||
|
|
63
|
+
!Number.isSafeInteger(scope.expiresAt) ||
|
|
64
|
+
scope.expiresAt - scope.issuedAt !== 5000 ||
|
|
65
|
+
now < scope.issuedAt ||
|
|
66
|
+
now >= scope.expiresAt)
|
|
67
|
+
deny();
|
|
68
|
+
}
|
|
69
|
+
async same(scope, read) {
|
|
70
|
+
this.fresh(scope);
|
|
71
|
+
const row = await read();
|
|
72
|
+
this.fresh(scope);
|
|
73
|
+
if (!row ||
|
|
74
|
+
row.instanceId !== scope.instanceId ||
|
|
75
|
+
row.organizationId !== scope.organizationId ||
|
|
76
|
+
row.stripeAccountId !== scope.accountId ||
|
|
77
|
+
row.bindingGeneration !== scope.bindingGeneration)
|
|
78
|
+
deny();
|
|
79
|
+
}
|
|
80
|
+
async get(scope, path) {
|
|
81
|
+
this.fresh(scope);
|
|
82
|
+
const result = await this.forward({
|
|
83
|
+
method: "GET",
|
|
84
|
+
path,
|
|
85
|
+
query: "",
|
|
86
|
+
stripeAccount: scope.accountId,
|
|
87
|
+
stripeVersion: scope.apiVersion,
|
|
88
|
+
scopedReadTimeoutMs: Math.max(1, Math.floor(scope.expiresAt - this.clock())),
|
|
89
|
+
});
|
|
90
|
+
this.fresh(scope);
|
|
91
|
+
if (result.status < 200 ||
|
|
92
|
+
result.status >= 300 ||
|
|
93
|
+
Buffer.byteLength(result.body, "utf8") > 1024 * 1024)
|
|
94
|
+
deny();
|
|
95
|
+
let value;
|
|
96
|
+
try {
|
|
97
|
+
value = JSON.parse(result.body);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return deny();
|
|
101
|
+
}
|
|
102
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
103
|
+
return deny();
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
async mode(scope) {
|
|
107
|
+
const balance = await this.get(scope, "/v1/balance");
|
|
108
|
+
if (balance.object !== "balance" || balance.livemode !== scope.livemode)
|
|
109
|
+
deny();
|
|
110
|
+
}
|
|
111
|
+
async issue(owner, request, read) {
|
|
112
|
+
const started = this.clock();
|
|
113
|
+
if (!id(request.accountId, "acct_") ||
|
|
114
|
+
typeof request.livemode !== "boolean" ||
|
|
115
|
+
!apiVersion(request.apiVersion))
|
|
116
|
+
return deny();
|
|
117
|
+
const row = await read();
|
|
118
|
+
if (!row ||
|
|
119
|
+
!uuid(row.bindingGeneration) ||
|
|
120
|
+
row.instanceId !== owner.id ||
|
|
121
|
+
row.organizationId !== owner.organizationId ||
|
|
122
|
+
row.stripeAccountId !== request.accountId)
|
|
123
|
+
return deny();
|
|
124
|
+
const scope = {
|
|
125
|
+
version: 1,
|
|
126
|
+
instanceId: owner.id,
|
|
127
|
+
organizationId: owner.organizationId,
|
|
128
|
+
accountId: row.stripeAccountId,
|
|
129
|
+
livemode: request.livemode,
|
|
130
|
+
bindingGeneration: row.bindingGeneration,
|
|
131
|
+
apiVersion: request.apiVersion,
|
|
132
|
+
issuedAt: started,
|
|
133
|
+
expiresAt: started + 5000,
|
|
134
|
+
};
|
|
135
|
+
const account = await this.get(scope, `/v1/accounts/${scope.accountId}`);
|
|
136
|
+
if (account.object !== "account" || account.id !== scope.accountId)
|
|
137
|
+
deny();
|
|
138
|
+
await this.mode(scope);
|
|
139
|
+
await this.same(scope, read);
|
|
140
|
+
const payload = Buffer.from(JSON.stringify(scope)).toString("base64url");
|
|
141
|
+
return {
|
|
142
|
+
scope,
|
|
143
|
+
contextToken: `${payload}.${this.mac(payload).toString("base64url")}`,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
checkout(owner, request, read) {
|
|
147
|
+
return this.scopedRead("checkout", owner, request, read);
|
|
148
|
+
}
|
|
149
|
+
paymentLink(owner, request, read) {
|
|
150
|
+
return this.scopedRead("payment-link", owner, request, read);
|
|
151
|
+
}
|
|
152
|
+
/** Fixed paired evidence read; never exposes an arbitrary event/proxy route. */
|
|
153
|
+
async pausedSubscription(owner, request, read) {
|
|
154
|
+
if (!id(request.eventId, "evt_") || !id(request.subscriptionId, "sub_"))
|
|
155
|
+
return deny();
|
|
156
|
+
const scope = this.readScope(owner, request);
|
|
157
|
+
await this.same(scope, read);
|
|
158
|
+
await this.mode(scope);
|
|
159
|
+
await this.same(scope, read);
|
|
160
|
+
const event = await this.get(scope, `/v1/events/${request.eventId}`);
|
|
161
|
+
await this.same(scope, read);
|
|
162
|
+
if (event.id !== request.eventId ||
|
|
163
|
+
event.object !== "event" ||
|
|
164
|
+
event.type !== "customer.subscription.paused" ||
|
|
165
|
+
event.livemode !== scope.livemode ||
|
|
166
|
+
(event.account != null && event.account !== scope.accountId) ||
|
|
167
|
+
event.context != null ||
|
|
168
|
+
!Number.isSafeInteger(event.created) ||
|
|
169
|
+
event.created < 0)
|
|
170
|
+
return deny();
|
|
171
|
+
const data = event.data;
|
|
172
|
+
const prior = data?.object;
|
|
173
|
+
const before = this.pausedCustomer(prior, request.subscriptionId, scope);
|
|
174
|
+
const subscription = await this.get(scope, `/v1/subscriptions/${request.subscriptionId}`);
|
|
175
|
+
await this.same(scope, read);
|
|
176
|
+
if (this.pausedCustomer(subscription, request.subscriptionId, scope) !==
|
|
177
|
+
before)
|
|
178
|
+
return deny();
|
|
179
|
+
const result = { scope, event, subscription };
|
|
180
|
+
if (Buffer.byteLength(JSON.stringify(result), "utf8") > 1024 * 1024)
|
|
181
|
+
return deny();
|
|
182
|
+
this.fresh(scope);
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
pausedCustomer(value, subscriptionId, scope) {
|
|
186
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
187
|
+
return deny();
|
|
188
|
+
const object = value;
|
|
189
|
+
if (object.id !== subscriptionId ||
|
|
190
|
+
object.object !== "subscription" ||
|
|
191
|
+
object.status !== "paused" ||
|
|
192
|
+
object.livemode !== scope.livemode)
|
|
193
|
+
return deny();
|
|
194
|
+
if (id(object.customer, "cus_"))
|
|
195
|
+
return object.customer;
|
|
196
|
+
const customer = object.customer;
|
|
197
|
+
if (!customer ||
|
|
198
|
+
typeof customer !== "object" ||
|
|
199
|
+
Array.isArray(customer) ||
|
|
200
|
+
customer.object !== "customer" ||
|
|
201
|
+
!id(customer.id, "cus_") ||
|
|
202
|
+
(Object.hasOwn(customer, "deleted") && customer.deleted !== false) ||
|
|
203
|
+
(Object.hasOwn(customer, "livemode") &&
|
|
204
|
+
customer.livemode !== scope.livemode))
|
|
205
|
+
return deny();
|
|
206
|
+
return customer.id;
|
|
207
|
+
}
|
|
208
|
+
readScope(owner, request) {
|
|
209
|
+
if (typeof request.contextToken !== "string" ||
|
|
210
|
+
request.contextToken.length > 4096)
|
|
211
|
+
return deny();
|
|
212
|
+
const parts = request.contextToken.split(".");
|
|
213
|
+
if (parts.length !== 2 || !parts.every((p) => /^[A-Za-z0-9_-]+$/.test(p)))
|
|
214
|
+
return deny();
|
|
215
|
+
const [payload, signature] = parts;
|
|
216
|
+
const actual = Buffer.from(signature, "base64url");
|
|
217
|
+
const expected = this.mac(payload);
|
|
218
|
+
if (actual.length !== expected.length ||
|
|
219
|
+
!timingSafeEqual(actual, expected) ||
|
|
220
|
+
actual.toString("base64url") !== signature)
|
|
221
|
+
return deny();
|
|
222
|
+
let scope;
|
|
223
|
+
try {
|
|
224
|
+
scope = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return deny();
|
|
228
|
+
}
|
|
229
|
+
if (!scope ||
|
|
230
|
+
scope.version !== 1 ||
|
|
231
|
+
scope.instanceId !== owner.id ||
|
|
232
|
+
scope.organizationId !== owner.organizationId ||
|
|
233
|
+
!id(scope.accountId, "acct_") ||
|
|
234
|
+
!uuid(scope.bindingGeneration) ||
|
|
235
|
+
typeof scope.livemode !== "boolean" ||
|
|
236
|
+
!apiVersion(scope.apiVersion) ||
|
|
237
|
+
scope.apiVersion !== request.apiVersion)
|
|
238
|
+
return deny();
|
|
239
|
+
return scope;
|
|
240
|
+
}
|
|
241
|
+
async scopedRead(kind, owner, request, read) {
|
|
242
|
+
if (typeof request.contextToken !== "string" ||
|
|
243
|
+
request.contextToken.length > 4096 ||
|
|
244
|
+
!id(request.id, kind === "checkout" ? "cs_" : "plink_"))
|
|
245
|
+
return deny();
|
|
246
|
+
const scope = this.readScope(owner, request);
|
|
247
|
+
await this.same(scope, read);
|
|
248
|
+
await this.mode(scope);
|
|
249
|
+
const object = await this.get(scope, kind === "checkout"
|
|
250
|
+
? `/v1/checkout/sessions/${request.id}`
|
|
251
|
+
: `/v1/payment_links/${request.id}`);
|
|
252
|
+
if (object.id !== request.id ||
|
|
253
|
+
object.object !==
|
|
254
|
+
(kind === "checkout" ? "checkout.session" : "payment_link") ||
|
|
255
|
+
object.livemode !== scope.livemode)
|
|
256
|
+
deny();
|
|
257
|
+
await this.same(scope, read);
|
|
258
|
+
return { scope, object };
|
|
259
|
+
}
|
|
260
|
+
}
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
* http://localhost:12111 (docker stripe/stripe-mock)
|
|
42
42
|
* MOCK_STRIPE_UPSTREAM_KEY the key sent upstream (default sk_test_123)
|
|
43
43
|
*/
|
|
44
|
-
import { randomBytes } from 'node:crypto';
|
|
44
|
+
import { randomBytes, randomUUID } from 'node:crypto';
|
|
45
|
+
import { PaymentsContextProtocol } from './payments-context.mjs';
|
|
45
46
|
|
|
46
47
|
const env = process.env;
|
|
47
48
|
const AUTO_ENABLE = !['0', 'false', 'no'].includes(
|
|
@@ -446,6 +447,7 @@ async function onboardingLink(ctx) {
|
|
|
446
447
|
ctx.state.accountCount = (ctx.state.accountCount ?? 0) + 1;
|
|
447
448
|
account = ctx.state.accounts[ctx.instanceId] = {
|
|
448
449
|
id: `acct_mock_${String(ctx.state.accountCount).padStart(4, '0')}`,
|
|
450
|
+
bindingGeneration: randomUUID(),
|
|
449
451
|
chargesEnabled: false,
|
|
450
452
|
payoutsEnabled: false,
|
|
451
453
|
detailsSubmitted: false,
|
|
@@ -466,6 +468,46 @@ function status(ctx) {
|
|
|
466
468
|
});
|
|
467
469
|
}
|
|
468
470
|
|
|
471
|
+
// Dedicated context routes never widen STRIPE_ALLOWLIST. Synthetic mode is
|
|
472
|
+
// test-only; configured upstream verifies its own actual account and mode.
|
|
473
|
+
async function scopedRead(ctx, operation) {
|
|
474
|
+
const read = async () => {
|
|
475
|
+
const account = accountFor(ctx);
|
|
476
|
+
return account ? {instanceId:ctx.instanceId, organizationId:`mock:${ctx.instanceId}`,
|
|
477
|
+
stripeAccountId:account.id, bindingGeneration:account.bindingGeneration} : null;
|
|
478
|
+
};
|
|
479
|
+
const protocol = new PaymentsContextProtocol(UPSTREAM_KEY, UPSTREAM ?? 'https://gateway-mock.invalid', async request => {
|
|
480
|
+
if (UPSTREAM) {
|
|
481
|
+
const response = await fetch(`${UPSTREAM}${request.path}`, {method:'GET', redirect:'error',
|
|
482
|
+
signal:AbortSignal.timeout(5000), headers:{authorization:`Bearer ${UPSTREAM_KEY}`,
|
|
483
|
+
'stripe-account':request.stripeAccount,'stripe-version':request.stripeVersion}});
|
|
484
|
+
return {status:response.status,body:await response.text()};
|
|
485
|
+
}
|
|
486
|
+
let object;
|
|
487
|
+
if (request.path === '/v1/balance') object = {object:'balance',livemode:false};
|
|
488
|
+
else if (request.path === `/v1/accounts/${request.stripeAccount}`) object = {object:'account',id:request.stripeAccount};
|
|
489
|
+
else {
|
|
490
|
+
const saved = ctx.state.objects.get(request.path.split('/').pop());
|
|
491
|
+
if (saved?.__account === request.stripeAccount) object = visible(saved);
|
|
492
|
+
}
|
|
493
|
+
return {status:object ? 200 : 404,body:JSON.stringify(object ?? {})};
|
|
494
|
+
});
|
|
495
|
+
try {
|
|
496
|
+
const fields = operation === 'issue' ? ['accountId','livemode','apiVersion'] : operation === 'pausedSubscription' ? ['contextToken','eventId','subscriptionId','apiVersion'] : ['contextToken','id','apiVersion'];
|
|
497
|
+
if (!ctx.body || typeof ctx.body !== 'object' || Array.isArray(ctx.body)
|
|
498
|
+
|| Object.keys(ctx.body).some(k => !fields.includes(k)) || ctx.req.url.includes('?')) throw new Error('invalid');
|
|
499
|
+
const minute = Math.floor(Date.now()/60000);
|
|
500
|
+
ctx.state.rate ??= {};
|
|
501
|
+
const key = `${ctx.instanceId}:${minute}`;
|
|
502
|
+
ctx.state.rate[key] = (ctx.state.rate[key] ?? 0)+1;
|
|
503
|
+
if (ctx.state.rate[key] > RPM) return stripeError(ctx,429,'rate_limit_error','Payments request limit exceeded','rate_limit');
|
|
504
|
+
const owner = {id:ctx.instanceId,organizationId:`mock:${ctx.instanceId}`};
|
|
505
|
+
return ctx.send(200, await protocol[operation](owner,ctx.body,read),{'cache-control':'no-store'});
|
|
506
|
+
} catch {
|
|
507
|
+
return stripeError(ctx,409,'invalid_request_error','Payment context is unavailable or no longer matches','payments_context_invalid');
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
469
511
|
async function stripeProxy(ctx) {
|
|
470
512
|
const method = ctx.req.method;
|
|
471
513
|
const path = ctx.path.replace(/^\/instance-gateway\/stripe/, '');
|
|
@@ -532,6 +574,10 @@ export default {
|
|
|
532
574
|
routes: [
|
|
533
575
|
{ method: 'POST', path: '/payments/onboarding-link', handler: onboardingLink },
|
|
534
576
|
{ method: 'GET', path: '/payments/status', handler: status },
|
|
577
|
+
{ method: 'POST', path: '/payments/context', handler: ctx => scopedRead(ctx,'issue') },
|
|
578
|
+
{ method: 'POST', path: '/payments/context/checkout-read', handler: ctx => scopedRead(ctx,'checkout') },
|
|
579
|
+
{ method: 'POST', path: '/payments/context/payment-link-read', handler: ctx => scopedRead(ctx,'paymentLink') },
|
|
580
|
+
{ method: 'POST', path: '/payments/context/paused-subscription-read', handler: ctx => scopedRead(ctx,'pausedSubscription') },
|
|
535
581
|
...['GET', 'POST', 'DELETE'].map((method) => ({ method, path: PROXY, handler: stripeProxy }))
|
|
536
582
|
],
|
|
537
583
|
vendorRoutes: [
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/** Portable policy shared by contract compilation and runtime authentication. */
|
|
2
|
+
export type PortableJwtPolicy = {
|
|
3
|
+
readonly scheme: 'jwt';
|
|
4
|
+
readonly headerName?: string;
|
|
5
|
+
readonly tokenPrefix?: string;
|
|
6
|
+
readonly sessionSchema?: Readonly<Record<string, unknown>>;
|
|
7
|
+
} & ({
|
|
8
|
+
readonly allowedRoles: readonly string[];
|
|
9
|
+
} | {
|
|
10
|
+
readonly allowedPermissions: readonly string[];
|
|
11
|
+
});
|
|
12
|
+
export type PortableHmacPolicy = {
|
|
13
|
+
readonly scheme: 'hmac';
|
|
14
|
+
readonly headerName?: string;
|
|
15
|
+
readonly tokenPrefix?: string;
|
|
16
|
+
};
|
|
17
|
+
export type PortableAuthPolicy = PortableJwtPolicy | PortableHmacPolicy;
|
|
18
|
+
/** Runtime keys and resource decoding belong to DI, never portable SDK assets. */
|
|
19
|
+
export type JwtRuntimeBinding = ({
|
|
20
|
+
readonly jwksPublicKeyUrl: string;
|
|
21
|
+
} | {
|
|
22
|
+
readonly signatureKey: string;
|
|
23
|
+
}) & {
|
|
24
|
+
readonly decodeResource?: (token: string) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
25
|
+
};
|
|
26
|
+
export type HmacRuntimeBinding = {
|
|
27
|
+
readonly secretKeys: Readonly<Record<string, string>>;
|
|
28
|
+
};
|
|
29
|
+
type RuntimeBinding<P extends PortableAuthPolicy> = P extends PortableJwtPolicy ? JwtRuntimeBinding : HmacRuntimeBinding;
|
|
30
|
+
type BoundPolicy<P> = Omit<P, 'scheme' | 'allowedRoles' | 'allowedPermissions'> & (P extends {
|
|
31
|
+
readonly allowedRoles: readonly string[];
|
|
32
|
+
} ? {
|
|
33
|
+
allowedRoles: Set<string>;
|
|
34
|
+
} : {}) & (P extends {
|
|
35
|
+
readonly allowedPermissions: readonly string[];
|
|
36
|
+
} ? {
|
|
37
|
+
allowedPermissions: Set<string>;
|
|
38
|
+
} : {});
|
|
39
|
+
type BoundContract<T extends {
|
|
40
|
+
readonly auth: PortableAuthPolicy;
|
|
41
|
+
}, B> = Omit<T, 'auth'> & {
|
|
42
|
+
auth: BoundPolicy<T['auth']> & (T['auth'] extends PortableJwtPolicy ? {
|
|
43
|
+
jwt: Omit<B, 'decodeResource'>;
|
|
44
|
+
} & Pick<B, Extract<keyof B, 'decodeResource'>> : {
|
|
45
|
+
hmac: B;
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
/** Bind credentials without allowing runtime configuration to override policy. */
|
|
49
|
+
export declare function bindRuntimeAuth<T extends {
|
|
50
|
+
readonly auth: PortableAuthPolicy;
|
|
51
|
+
}, B extends RuntimeBinding<T['auth']>>(details: T, binding: B): BoundContract<T, B>;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=bindRuntimeAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bindRuntimeAuth.d.ts","sourceRoot":"","sources":["../../src/http/bindRuntimeAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bindRuntimeAuth.test.d.ts","sourceRoot":"","sources":["../../src/http/bindRuntimeAuth.test.ts"],"names":[],"mappings":""}
|
package/lib/http/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from './bindRuntimeAuth';
|
|
1
2
|
export type { ParsedQs } from 'qs';
|
|
2
3
|
export * from './application/expressLikeApplication';
|
|
3
4
|
export * from './cluster/cluster.types';
|
|
@@ -53,4 +54,5 @@ export * from './rateLimit/index';
|
|
|
53
54
|
export * from './types/sdk.types';
|
|
54
55
|
export { MapToSdk } from './types/sdk.types';
|
|
55
56
|
export * from './types/typedHandler.types';
|
|
57
|
+
export * from './registerDelegatedSurface';
|
|
56
58
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/http/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACnC,cAAc,sCAAsC,CAAC;AACrD,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0CAA0C,CAAC;AACzD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,wDAAwD,CAAC;AACvE,cAAc,yCAAyC,CAAC;AACxD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sCAAsC,CAAC;AACrD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AACnD,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AACrD,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,cAAc,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACnC,cAAc,sCAAsC,CAAC;AACrD,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,mBAAmB,CAAC;AAClC,cAAc,0CAA0C,CAAC;AACzD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+CAA+C,CAAC;AAC9D,cAAc,wDAAwD,CAAC;AACvE,cAAc,yCAAyC,CAAC;AACxD,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sCAAsC,CAAC;AACrD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,oCAAoC,CAAC;AACnD,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC;AAChD,cAAc,sCAAsC,CAAC;AACrD,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAE3C,cAAc,4BAA4B,CAAC"}
|