@learncard/lca-api-service 1.5.3 → 1.6.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/.env.example +10 -0
- package/CHANGELOG.md +26 -0
- package/bundle.mjs +1 -1
- package/dist/app.d.ts +4 -1
- package/dist/config/cacheEnvironment.d.ts +4 -4
- package/dist/config/environment.d.ts +145 -114
- package/dist/config/oidcEnvironment.d.ts +22 -22
- package/dist/didkit_wasm_bg.wasm +0 -0
- package/dist/helpers/bedrockGeneration.d.ts +17 -0
- package/dist/helpers/bedrockGeneration.test.d.ts +1 -0
- package/dist/helpers/bedrockSchema.d.ts +10 -0
- package/dist/helpers/imageGeneration.d.ts +42 -0
- package/dist/helpers/imageGeneration.test.d.ts +1 -0
- package/dist/index.js +2 -2
- package/dist/models/Notification.d.ts +3 -1
- package/dist/publish-metafile.json +1 -1
- package/dist/routes/ai.skill-icons.test.d.ts +1 -0
- package/dist/routes/keys.d.ts +1 -0
- package/dist/routes/notifications.d.ts +3 -1
- package/dist/types/notifications.d.ts +3 -1
- package/docs/bedrock-generation.md +119 -0
- package/docs/image-generation.md +120 -0
- package/package.json +20 -15
- package/scripts/node24-runtime.cjs +9 -0
- package/scripts/verify-node24-layer.cjs +49 -0
- package/serverless-local.yml +3 -1
- package/serverless.function-env.cjs +2 -4
- package/serverless.yml +76 -3
- package/src/config/environment.ts +14 -0
- package/src/helpers/bedrockGeneration.test.ts +222 -0
- package/src/helpers/bedrockGeneration.ts +110 -0
- package/src/helpers/bedrockSchema.ts +352 -0
- package/src/helpers/imageGeneration.test.ts +456 -0
- package/src/helpers/imageGeneration.ts +432 -0
- package/src/routes/ai.skill-icons.test.ts +92 -0
- package/src/routes/ai.test.ts +68 -91
- package/src/routes/ai.ts +31 -143
- package/src/routes/keys.ts +18 -0
- package/src/services/escrow-enclave/enclaveTrustAnchors.ts +19 -0
- package/src/services/escrow-enclave/logFailure.test.ts +8 -0
- package/src/services/escrow-enclave/logFailure.ts +17 -0
- package/src/services/escrow-enclave/remoteEnclave.tls.test.ts +10 -0
- package/test/keys-auth-share-escrow.spec.ts +103 -0
- package/test/oidc.spec.ts +41 -2
- package/tsconfig.bedrock.json +10 -0
package/test/oidc.spec.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { issueLoginTicket, redeemLoginTicket } from '../src/cache/login-tickets'
|
|
|
6
6
|
import cache from '@cache';
|
|
7
7
|
import { GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';
|
|
8
8
|
import { getOidcSigningKey, resetOidcSigningKeyForTests } from '../src/helpers/oidc.helpers';
|
|
9
|
+
import { ACCESS_TOKEN_PREFIX } from '../src/helpers/login-ticket.helpers';
|
|
9
10
|
|
|
10
11
|
const { env, entries, sendSecret } = vi.hoisted(() => ({
|
|
11
12
|
sendSecret: vi.fn(),
|
|
@@ -188,8 +189,12 @@ beforeEach(async () => {
|
|
|
188
189
|
});
|
|
189
190
|
});
|
|
190
191
|
afterEach(async () => {
|
|
191
|
-
|
|
192
|
-
|
|
192
|
+
try {
|
|
193
|
+
await app.close();
|
|
194
|
+
} finally {
|
|
195
|
+
vi.useRealTimers();
|
|
196
|
+
vi.restoreAllMocks();
|
|
197
|
+
}
|
|
193
198
|
});
|
|
194
199
|
|
|
195
200
|
describe('OIDC provider', () => {
|
|
@@ -397,6 +402,11 @@ describe('OIDC provider', () => {
|
|
|
397
402
|
it.each<BasicMode>(['encoded', 'raw', false])(
|
|
398
403
|
'exchanges a code using Basic=%s and verifies RS256 through served JWKS',
|
|
399
404
|
async basic => {
|
|
405
|
+
// Freeze wall-clock time only; Fastify's I/O timers keep running normally.
|
|
406
|
+
// expires_in is remaining time, so an uncontrolled second boundary can
|
|
407
|
+
// make it 299 even though the signed JWT lifetime is exactly 300 seconds.
|
|
408
|
+
vi.useFakeTimers({ toFake: ['Date'] });
|
|
409
|
+
vi.setSystemTime(new Date('2026-10-14T12:00:00.999Z'));
|
|
400
410
|
const response = await exchange(await code(), {}, basic);
|
|
401
411
|
expect(response.statusCode).toBe(200);
|
|
402
412
|
const tokens = response.json();
|
|
@@ -427,6 +437,35 @@ describe('OIDC provider', () => {
|
|
|
427
437
|
expect(response.headers.pragma).toBe('no-cache');
|
|
428
438
|
}
|
|
429
439
|
);
|
|
440
|
+
it('reports 299 seconds remaining when access-token persistence crosses a second', async () => {
|
|
441
|
+
vi.useFakeTimers({ toFake: ['Date'] });
|
|
442
|
+
const start = new Date('2026-10-14T12:00:00.999Z');
|
|
443
|
+
vi.setSystemTime(start);
|
|
444
|
+
const set = cache.set.bind(cache);
|
|
445
|
+
vi.spyOn(cache, 'set').mockImplementation(async (...args) => {
|
|
446
|
+
const result = await set(...args);
|
|
447
|
+
if (args[0].startsWith(ACCESS_TOKEN_PREFIX)) {
|
|
448
|
+
// Advance after JWT signing, before expires_in is calculated.
|
|
449
|
+
vi.setSystemTime(start.getTime() + 1);
|
|
450
|
+
}
|
|
451
|
+
return result;
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
const response = await exchange(await code());
|
|
455
|
+
expect(response.statusCode).toBe(200);
|
|
456
|
+
const tokens = response.json();
|
|
457
|
+
const jwks = createLocalJWKSet((await app.inject('/oidc/jwks')).json());
|
|
458
|
+
const options = { issuer: env.OIDC_ISSUER, audience: env.OIDC_CLIENT_ID };
|
|
459
|
+
const { payload } = await jwtVerify(tokens.id_token, jwks, options);
|
|
460
|
+
expect(payload.exp! - payload.iat!).toBe(300);
|
|
461
|
+
expect(tokens.expires_in).toBe(299);
|
|
462
|
+
|
|
463
|
+
// The clock control must not hide an extended JWT lifetime.
|
|
464
|
+
vi.setSystemTime(payload.exp! * 1000);
|
|
465
|
+
await expect(jwtVerify(tokens.id_token, jwks, options)).rejects.toMatchObject({
|
|
466
|
+
code: 'ERR_JWT_EXPIRED',
|
|
467
|
+
});
|
|
468
|
+
});
|
|
430
469
|
it('URL-decodes Basic client credentials', async () => {
|
|
431
470
|
env.OIDC_CLIENT_SECRET = 'a+b:c %';
|
|
432
471
|
expect((await exchange(await code(), {}, 'encoded')).statusCode).toBe(200);
|