@de-otio/trellis 0.12.2 → 0.12.3
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pre-token-generation.d.ts","sourceRoot":"","sources":["../../src/lambda/pre-token-generation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAEV,kCAAkC,EACnC,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"pre-token-generation.d.ts","sourceRoot":"","sources":["../../src/lambda/pre-token-generation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAEV,kCAAkC,EACnC,MAAM,YAAY,CAAC;AAsKpB,eAAO,MAAM,OAAO,EAAE,kCAoKrB,CAAC"}
|
|
@@ -37,6 +37,17 @@ const DRIFT_CLAIMS = {
|
|
|
37
37
|
tenantRole: "",
|
|
38
38
|
handle: "",
|
|
39
39
|
};
|
|
40
|
+
// Read-after-write retry budget for the RDS fallback. On a brand-new signup,
|
|
41
|
+
// the first token can be minted before PostConfirmation's provisioning
|
|
42
|
+
// transaction is visible; a single miss would emit the drift sentinel (empty
|
|
43
|
+
// `custom:userId`) and break every downstream `where:{id}` lookup until the
|
|
44
|
+
// user re-auths. We retry the load a bounded number of times so the write can
|
|
45
|
+
// land. Genuine drift (post-RDS-restore) simply exhausts the budget and falls
|
|
46
|
+
// through to the sentinel exactly as before. Runtime config, not compiled-in
|
|
47
|
+
// constants (threshold-secrecy rule).
|
|
48
|
+
const DEFAULT_RDS_RETRY_MAX = 4;
|
|
49
|
+
const DEFAULT_RDS_RETRY_DELAY_MS = 150;
|
|
50
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
40
51
|
function parseIdpGroups(raw) {
|
|
41
52
|
if (!raw)
|
|
42
53
|
return [];
|
|
@@ -138,6 +149,15 @@ export const handler = async (event) => {
|
|
|
138
149
|
// Without invalidation, suspended users keep valid claims for up to one
|
|
139
150
|
// cache TTL (DEFAULT_CACHE_TTL_SECONDS = 3600s). Tracked as G2 finding H3.
|
|
140
151
|
let claims = await claimsCache.get(cognitoSub);
|
|
152
|
+
// A cached entry with an empty userId is never legitimate: a real user's
|
|
153
|
+
// claims always carry the cuid, and the drift sentinel is never written to
|
|
154
|
+
// the cache (both `put` sites guard on a truthy userId). Treat such an entry
|
|
155
|
+
// as a miss so the RDS fallback can recover the real userId rather than
|
|
156
|
+
// serving a token with an empty `custom:userId`.
|
|
157
|
+
if (claims && !claims.userId) {
|
|
158
|
+
logger.warn("pretoken.empty_cache_entry", { cognitoSub });
|
|
159
|
+
claims = null;
|
|
160
|
+
}
|
|
141
161
|
let cacheHit = !!claims;
|
|
142
162
|
if (!claims) {
|
|
143
163
|
// RDS is consulted only on a genuine cache miss. Emit a filterable event so
|
|
@@ -158,9 +178,33 @@ export const handler = async (event) => {
|
|
|
158
178
|
error: err?.code ?? "unknown",
|
|
159
179
|
});
|
|
160
180
|
}
|
|
161
|
-
|
|
181
|
+
// Bounded read-after-write retry: re-read until the user row is visible or
|
|
182
|
+
// the budget is spent (see DEFAULT_RDS_RETRY_* above). Each attempt is wrapped
|
|
183
|
+
// in the breaker, so a saturated DB still fast-fails (the breaker throws and
|
|
184
|
+
// issuance fails) rather than being retried into an exhausted instance — a
|
|
185
|
+
// null return is a successful read, not a breaker failure, so retrying it is
|
|
186
|
+
// safe.
|
|
187
|
+
const retryMax = Math.max(1, Number(process.env.PRETOKEN_RDS_RETRY_MAX ?? DEFAULT_RDS_RETRY_MAX));
|
|
188
|
+
const retryDelayMs = Math.max(0, Number(process.env.PRETOKEN_RDS_RETRY_DELAY_MS ?? DEFAULT_RDS_RETRY_DELAY_MS));
|
|
189
|
+
let loaded = await withLambdaDbBreaker(() => loadFromRds(db, cognitoSub, federated, preferredTenantId), "pretoken.load_from_rds");
|
|
190
|
+
let rdsAttempts = 1;
|
|
191
|
+
while (!loaded.user && rdsAttempts < retryMax) {
|
|
192
|
+
await sleep(retryDelayMs);
|
|
193
|
+
loaded = await withLambdaDbBreaker(() => loadFromRds(db, cognitoSub, federated, preferredTenantId), "pretoken.load_from_rds");
|
|
194
|
+
rdsAttempts++;
|
|
195
|
+
}
|
|
196
|
+
if (rdsAttempts > 1) {
|
|
197
|
+
// Fires only when the race actually occurred — a low-noise signal that
|
|
198
|
+
// distinguishes the read-after-write window from steady state, and shows
|
|
199
|
+
// whether the retry recovered the row.
|
|
200
|
+
logger.warn("pretoken.rds_retry", {
|
|
201
|
+
cognitoSub,
|
|
202
|
+
rdsAttempts,
|
|
203
|
+
recovered: !!loaded.user,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
162
206
|
if (!loaded.user) {
|
|
163
|
-
logger.warn("pretoken.drift", { cognitoSub });
|
|
207
|
+
logger.warn("pretoken.drift", { cognitoSub, rdsAttempts });
|
|
164
208
|
claims = { ...DRIFT_CLAIMS };
|
|
165
209
|
writeTokenClaims(event, claims);
|
|
166
210
|
return event;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pre-token-generation.js","sourceRoot":"","sources":["../../src/lambda/pre-token-generation.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"pre-token-generation.js","sourceRoot":"","sources":["../../src/lambda/pre-token-generation.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -51,6 +51,20 @@ const DRIFT_CLAIMS: CachedClaims = {
|
|
|
51
51
|
handle: "",
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
+
// Read-after-write retry budget for the RDS fallback. On a brand-new signup,
|
|
55
|
+
// the first token can be minted before PostConfirmation's provisioning
|
|
56
|
+
// transaction is visible; a single miss would emit the drift sentinel (empty
|
|
57
|
+
// `custom:userId`) and break every downstream `where:{id}` lookup until the
|
|
58
|
+
// user re-auths. We retry the load a bounded number of times so the write can
|
|
59
|
+
// land. Genuine drift (post-RDS-restore) simply exhausts the budget and falls
|
|
60
|
+
// through to the sentinel exactly as before. Runtime config, not compiled-in
|
|
61
|
+
// constants (threshold-secrecy rule).
|
|
62
|
+
const DEFAULT_RDS_RETRY_MAX = 4;
|
|
63
|
+
const DEFAULT_RDS_RETRY_DELAY_MS = 150;
|
|
64
|
+
|
|
65
|
+
const sleep = (ms: number): Promise<void> =>
|
|
66
|
+
new Promise((resolve) => setTimeout(resolve, ms));
|
|
67
|
+
|
|
54
68
|
function parseIdpGroups(raw: string | undefined | null): string[] {
|
|
55
69
|
if (!raw) return [];
|
|
56
70
|
return raw
|
|
@@ -191,6 +205,15 @@ export const handler: PreTokenGenerationV2TriggerHandler = async (event) => {
|
|
|
191
205
|
// Without invalidation, suspended users keep valid claims for up to one
|
|
192
206
|
// cache TTL (DEFAULT_CACHE_TTL_SECONDS = 3600s). Tracked as G2 finding H3.
|
|
193
207
|
let claims = await claimsCache.get(cognitoSub);
|
|
208
|
+
// A cached entry with an empty userId is never legitimate: a real user's
|
|
209
|
+
// claims always carry the cuid, and the drift sentinel is never written to
|
|
210
|
+
// the cache (both `put` sites guard on a truthy userId). Treat such an entry
|
|
211
|
+
// as a miss so the RDS fallback can recover the real userId rather than
|
|
212
|
+
// serving a token with an empty `custom:userId`.
|
|
213
|
+
if (claims && !claims.userId) {
|
|
214
|
+
logger.warn("pretoken.empty_cache_entry", { cognitoSub });
|
|
215
|
+
claims = null;
|
|
216
|
+
}
|
|
194
217
|
let cacheHit = !!claims;
|
|
195
218
|
|
|
196
219
|
if (!claims) {
|
|
@@ -211,13 +234,47 @@ export const handler: PreTokenGenerationV2TriggerHandler = async (event) => {
|
|
|
211
234
|
error: (err as { code?: string })?.code ?? "unknown",
|
|
212
235
|
});
|
|
213
236
|
}
|
|
214
|
-
|
|
237
|
+
|
|
238
|
+
// Bounded read-after-write retry: re-read until the user row is visible or
|
|
239
|
+
// the budget is spent (see DEFAULT_RDS_RETRY_* above). Each attempt is wrapped
|
|
240
|
+
// in the breaker, so a saturated DB still fast-fails (the breaker throws and
|
|
241
|
+
// issuance fails) rather than being retried into an exhausted instance — a
|
|
242
|
+
// null return is a successful read, not a breaker failure, so retrying it is
|
|
243
|
+
// safe.
|
|
244
|
+
const retryMax = Math.max(
|
|
245
|
+
1,
|
|
246
|
+
Number(process.env.PRETOKEN_RDS_RETRY_MAX ?? DEFAULT_RDS_RETRY_MAX),
|
|
247
|
+
);
|
|
248
|
+
const retryDelayMs = Math.max(
|
|
249
|
+
0,
|
|
250
|
+
Number(process.env.PRETOKEN_RDS_RETRY_DELAY_MS ?? DEFAULT_RDS_RETRY_DELAY_MS),
|
|
251
|
+
);
|
|
252
|
+
let loaded = await withLambdaDbBreaker(
|
|
215
253
|
() => loadFromRds(db, cognitoSub, federated, preferredTenantId),
|
|
216
254
|
"pretoken.load_from_rds",
|
|
217
255
|
);
|
|
256
|
+
let rdsAttempts = 1;
|
|
257
|
+
while (!loaded.user && rdsAttempts < retryMax) {
|
|
258
|
+
await sleep(retryDelayMs);
|
|
259
|
+
loaded = await withLambdaDbBreaker(
|
|
260
|
+
() => loadFromRds(db, cognitoSub, federated, preferredTenantId),
|
|
261
|
+
"pretoken.load_from_rds",
|
|
262
|
+
);
|
|
263
|
+
rdsAttempts++;
|
|
264
|
+
}
|
|
265
|
+
if (rdsAttempts > 1) {
|
|
266
|
+
// Fires only when the race actually occurred — a low-noise signal that
|
|
267
|
+
// distinguishes the read-after-write window from steady state, and shows
|
|
268
|
+
// whether the retry recovered the row.
|
|
269
|
+
logger.warn("pretoken.rds_retry", {
|
|
270
|
+
cognitoSub,
|
|
271
|
+
rdsAttempts,
|
|
272
|
+
recovered: !!loaded.user,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
218
275
|
|
|
219
276
|
if (!loaded.user) {
|
|
220
|
-
logger.warn("pretoken.drift", { cognitoSub });
|
|
277
|
+
logger.warn("pretoken.drift", { cognitoSub, rdsAttempts });
|
|
221
278
|
claims = { ...DRIFT_CLAIMS };
|
|
222
279
|
writeTokenClaims(event, claims);
|
|
223
280
|
return event;
|