@learncard/learn-cloud-service 2.5.34 → 2.5.36

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 (124) hide show
  1. package/.env.example +24 -12
  2. package/CHANGELOG.md +43 -0
  3. package/bootstrapLambda.test.ts +68 -0
  4. package/config/config.dev.json +8 -0
  5. package/config/config.example.json +8 -0
  6. package/config/config.json +1 -0
  7. package/config/config.production.json +8 -0
  8. package/config/config.scouts.dev.json +3 -0
  9. package/config/config.scouts.production.json +4 -0
  10. package/didWebLambda.test.ts +41 -0
  11. package/didWebLambda.ts +13 -19
  12. package/didWebLambdaApp.ts +23 -0
  13. package/dist/accesslayer/share-content/delete.d.ts +5 -0
  14. package/dist/accesslayer/share-content/delete.d.ts.map +1 -0
  15. package/dist/accesslayer/share-content/index.d.ts +8 -0
  16. package/dist/accesslayer/share-content/index.d.ts.map +1 -0
  17. package/dist/accesslayer/share-content/initialize.d.ts +5 -0
  18. package/dist/accesslayer/share-content/initialize.d.ts.map +1 -0
  19. package/dist/accesslayer/share-content/internal.d.ts +12 -0
  20. package/dist/accesslayer/share-content/internal.d.ts.map +1 -0
  21. package/dist/accesslayer/share-content/put.d.ts +5 -0
  22. package/dist/accesslayer/share-content/put.d.ts.map +1 -0
  23. package/dist/accesslayer/share-content/read.d.ts +7 -0
  24. package/dist/accesslayer/share-content/read.d.ts.map +1 -0
  25. package/dist/accesslayer/share-content/types.d.ts +85 -0
  26. package/dist/accesslayer/share-content/types.d.ts.map +1 -0
  27. package/dist/config/applyDockerStageConfig.d.ts +2 -0
  28. package/dist/config/applyDockerStageConfig.d.ts.map +1 -0
  29. package/dist/config/environment.d.ts +12 -0
  30. package/dist/config/environment.d.ts.map +1 -1
  31. package/dist/config/serverlessFunctionEnv.test.d.ts +2 -0
  32. package/dist/config/serverlessFunctionEnv.test.d.ts.map +1 -0
  33. package/dist/config/stageConfig.d.ts +10 -0
  34. package/dist/config/stageConfig.d.ts.map +1 -0
  35. package/dist/config/stageConfig.test.d.ts +2 -0
  36. package/dist/config/stageConfig.test.d.ts.map +1 -0
  37. package/dist/didkit_wasm_bg.wasm +0 -0
  38. package/dist/docker-entry.d.ts +1 -1
  39. package/dist/docker-entry.d.ts.map +1 -1
  40. package/dist/helpers/share-content-auth/adapters.d.ts +12 -0
  41. package/dist/helpers/share-content-auth/adapters.d.ts.map +1 -0
  42. package/dist/helpers/share-content-auth/canonical.d.ts +15 -0
  43. package/dist/helpers/share-content-auth/canonical.d.ts.map +1 -0
  44. package/dist/helpers/share-content-auth/claims.d.ts +19 -0
  45. package/dist/helpers/share-content-auth/claims.d.ts.map +1 -0
  46. package/dist/helpers/share-content-auth/config.d.ts +12 -0
  47. package/dist/helpers/share-content-auth/config.d.ts.map +1 -0
  48. package/dist/helpers/share-content-auth/index.d.ts +8 -0
  49. package/dist/helpers/share-content-auth/index.d.ts.map +1 -0
  50. package/dist/helpers/share-content-auth/token.d.ts +28 -0
  51. package/dist/helpers/share-content-auth/token.d.ts.map +1 -0
  52. package/dist/helpers/share-content-auth/types.d.ts +70 -0
  53. package/dist/helpers/share-content-auth/types.d.ts.map +1 -0
  54. package/dist/helpers/share-content-auth/verifier.d.ts +9 -0
  55. package/dist/helpers/share-content-auth/verifier.d.ts.map +1 -0
  56. package/dist/index.js +2 -2
  57. package/dist/models/ShareContent.d.ts +160 -0
  58. package/dist/models/ShareContent.d.ts.map +1 -0
  59. package/dist/models/index.d.ts +1 -0
  60. package/dist/models/index.d.ts.map +1 -1
  61. package/dist/share-content/config.d.ts +28 -0
  62. package/dist/share-content/config.d.ts.map +1 -0
  63. package/dist/share-content/index.d.ts +6 -0
  64. package/dist/share-content/index.d.ts.map +1 -0
  65. package/dist/share-content/plugin.d.ts +5 -0
  66. package/dist/share-content/plugin.d.ts.map +1 -0
  67. package/dist/share-content/production.d.ts +15 -0
  68. package/dist/share-content/production.d.ts.map +1 -0
  69. package/dist/share-content/runtime.d.ts +23 -0
  70. package/dist/share-content/runtime.d.ts.map +1 -0
  71. package/dist/share-content/types.d.ts +23 -0
  72. package/dist/share-content/types.d.ts.map +1 -0
  73. package/esbuildPlugins.cjs +1 -0
  74. package/lambda.ts +22 -92
  75. package/lambdaApp.ts +163 -0
  76. package/oidcLambda.test.ts +41 -0
  77. package/oidcLambda.ts +13 -19
  78. package/oidcLambdaApp.ts +23 -0
  79. package/package.json +18 -16
  80. package/serverless-local.yml +3 -1
  81. package/serverless.function-env.cjs +31 -0
  82. package/serverless.yml +31 -22
  83. package/src/accesslayer/share-content/delete.ts +124 -0
  84. package/src/accesslayer/share-content/index.ts +70 -0
  85. package/src/accesslayer/share-content/initialize.ts +24 -0
  86. package/src/accesslayer/share-content/internal.ts +89 -0
  87. package/src/accesslayer/share-content/put.ts +93 -0
  88. package/src/accesslayer/share-content/read.ts +124 -0
  89. package/src/accesslayer/share-content/types.ts +155 -0
  90. package/src/config/applyDockerStageConfig.ts +6 -0
  91. package/src/config/environment.ts +33 -0
  92. package/src/config/serverlessFunctionEnv.test.ts +81 -0
  93. package/src/config/stageConfig.test.ts +26 -0
  94. package/src/config/stageConfig.ts +24 -0
  95. package/src/docker-entry.ts +21 -0
  96. package/src/helpers/share-content-auth/adapters.ts +48 -0
  97. package/src/helpers/share-content-auth/canonical.ts +91 -0
  98. package/src/helpers/share-content-auth/claims.ts +164 -0
  99. package/src/helpers/share-content-auth/config.ts +160 -0
  100. package/src/helpers/share-content-auth/index.ts +59 -0
  101. package/src/helpers/share-content-auth/token.ts +148 -0
  102. package/src/helpers/share-content-auth/types.ts +195 -0
  103. package/src/helpers/share-content-auth/verifier.ts +220 -0
  104. package/src/models/ShareContent.ts +198 -0
  105. package/src/models/index.ts +1 -0
  106. package/src/share-content/config.ts +199 -0
  107. package/src/share-content/index.ts +5 -0
  108. package/src/share-content/plugin.ts +317 -0
  109. package/src/share-content/production.ts +107 -0
  110. package/src/share-content/runtime.ts +90 -0
  111. package/src/share-content/types.ts +59 -0
  112. package/test/share-content-auth.spec.ts +1161 -0
  113. package/test/share-content-config.spec.ts +252 -0
  114. package/test/share-content-didkit.spec.ts +411 -0
  115. package/test/share-content-endpoint.spec.ts +825 -0
  116. package/test/share-content-redis-setup.ts +18 -0
  117. package/test/share-content.spec.ts +681 -0
  118. package/vitest.config.ts +4 -0
  119. package/vitest.share-content-config-unit.config.ts +8 -0
  120. package/vitest.share-content-endpoint.config.ts +21 -0
  121. package/vitest.share-content.config.ts +19 -0
  122. package/xApiLambda.test.ts +41 -0
  123. package/xApiLambda.ts +13 -19
  124. package/xApiLambdaApp.ts +23 -0
package/.env.example CHANGED
@@ -1,23 +1,35 @@
1
- # LearnCloud service environment
2
- # Copy to .env. Validation runs before database/client initialization.
1
+ # LearnCloud: copy to .env. Values below are disposable local examples, not deploy secrets.
2
+ # Public configuration lives in config/config.json and config/config.<stage>.json.
3
+ # Precedence: schema defaults < base < stage < Lambda runtime bundle < non-empty real env.
4
+ # CONFIG_STAGE=dev or production opts local/Docker/offline into checked-in stage settings.
5
+ # Without CONFIG_STAGE, keep using local env and schema defaults as before.
6
+ # Lambda selects LAMBDA_STAGE; the bundle is learn-cloud-service/<stage>/runtime-secrets.
7
+ # Leave RUNTIME_SECRETS_ID unset locally. Keep GitHub fallbacks for rollback.
8
+ CONFIG_STAGE=
9
+ RUNTIME_SECRETS_ID=
3
10
 
4
- NODE_ENV=development
5
- PORT=3000
11
+ # Required credentials: replace every example before connecting to shared services.
6
12
  LEARN_CLOUD_SEED=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
7
13
  LEARN_CLOUD_MONGO_URI=mongodb://localhost:27017
8
14
  LEARN_CLOUD_MONGO_DB_NAME=learncloud
9
- DOMAIN_NAME=
10
- SERVER_URL=http://localhost:4100
11
- XAPI_ENDPOINT=
12
15
 
16
+ # Optional runtime credentials, including the private xAPI endpoint.
17
+ XAPI_ENDPOINT=
18
+ XAPI_USERNAME=
19
+ XAPI_PASSWORD=
20
+ JWT_SIGNING_KEY=
21
+ SENTRY_DSN=
13
22
  # Configure both RSA values or leave both empty to generate an ephemeral pair.
14
23
  RSA_PRIVATE_KEY=
15
24
  RSA_PUBLIC_KEY=
16
25
 
26
+ # Local infrastructure. Explicit env wins over a selected stage.
27
+ NODE_ENV=development
28
+ IS_OFFLINE=true
29
+ PORT=3000
17
30
  REDIS_HOST=
18
31
  REDIS_PORT=
19
- SENTRY_DSN=
20
- SENTRY_ENV=development
21
- IS_OFFLINE=false
22
- SKIP_DIDKIT_NAPI=false
23
- CI=false
32
+ # Local URL override, if needed: SERVER_URL=http://localhost:4100.
33
+ # SENTRY_ENV and SHARE_CONTENT_* trust settings come from the selected stage.
34
+ # Self-hosters can register config/config.example.json as their own stage or use explicit env.
35
+ # SENTRY_AUTH_TOKEN / SENTRY_ORG / SENTRY_PROJECT belong only in the build environment.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,48 @@
1
1
  # @learncard/network-brain-service
2
2
 
3
+ ## 2.5.36
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1670](https://github.com/learningeconomy/LearnCard/pull/1670) [`7656a57d30c6d80b8a25a8bb14bcd3b08b3648c2`](https://github.com/learningeconomy/LearnCard/commit/7656a57d30c6d80b8a25a8bb14bcd3b08b3648c2) Thanks [@Custard7](https://github.com/Custard7)! - Adopt the shared service-config model: load checked-in non-secret per-stage configuration before environment validation, bootstrap every Lambda entrypoint through the shared lazy loader, and deliver runtime secrets through an optional AWS Secrets Manager bundle with a per-value fallback for stages without one.
8
+
9
+ - [#1670](https://github.com/learningeconomy/LearnCard/pull/1670) [`7656a57d30c6d80b8a25a8bb14bcd3b08b3648c2`](https://github.com/learningeconomy/LearnCard/commit/7656a57d30c6d80b8a25a8bb14bcd3b08b3648c2) Thanks [@Custard7](https://github.com/Custard7)! - Select backend stage files by tenant as well as stage. `CONFIG_TENANT=scouts` loads `config.scouts.<stage>.json` (generated from the live ScoutPass Lambdas), so ScoutPass deployments no longer inherit LearnCard domains, trust settings or seed-encryption flags; a named tenant without a stage file fails closed. `ESCROW_ENCLAVE_MODE` is now forwarded in runtime-secrets bundle mode too.
10
+
11
+ - Updated dependencies [[`6209da80c52ac056a7644dab14669192740c9dad`](https://github.com/learningeconomy/LearnCard/commit/6209da80c52ac056a7644dab14669192740c9dad), [`5890451789b18afee45dc5ecbab3fa30aa90f085`](https://github.com/learningeconomy/LearnCard/commit/5890451789b18afee45dc5ecbab3fa30aa90f085), [`1387cd0a08fa6b0a706c86a5a0376b6c7d706856`](https://github.com/learningeconomy/LearnCard/commit/1387cd0a08fa6b0a706c86a5a0376b6c7d706856), [`d7ca528898d988c65f0dc7084cfdcd41767648c5`](https://github.com/learningeconomy/LearnCard/commit/d7ca528898d988c65f0dc7084cfdcd41767648c5), [`8f3bc66ab3d3e5e1edb3fbf5f362025875a914ba`](https://github.com/learningeconomy/LearnCard/commit/8f3bc66ab3d3e5e1edb3fbf5f362025875a914ba), [`1387cd0a08fa6b0a706c86a5a0376b6c7d706856`](https://github.com/learningeconomy/LearnCard/commit/1387cd0a08fa6b0a706c86a5a0376b6c7d706856), [`267cf40291b3a63caf178857be0e57feaf5e0948`](https://github.com/learningeconomy/LearnCard/commit/267cf40291b3a63caf178857be0e57feaf5e0948), [`7656a57d30c6d80b8a25a8bb14bcd3b08b3648c2`](https://github.com/learningeconomy/LearnCard/commit/7656a57d30c6d80b8a25a8bb14bcd3b08b3648c2), [`c78c982f9f4911f1ca2973380f19d80db775e012`](https://github.com/learningeconomy/LearnCard/commit/c78c982f9f4911f1ca2973380f19d80db775e012), [`590adf48867d6c6fd504e66a11c9827d5102122d`](https://github.com/learningeconomy/LearnCard/commit/590adf48867d6c6fd504e66a11c9827d5102122d)]:
12
+ - @learncard/types@5.23.0
13
+ - @learncard/service-config@0.1.1
14
+ - @learncard/didkit-plugin@1.10.3
15
+ - @learncard/core@9.4.38
16
+ - @learncard/helpers@1.6.2
17
+ - @learncard/did-web-plugin@1.1.38
18
+ - @learncard/didkey-plugin@1.1.38
19
+ - @learncard/didkit-plugin-node@0.3.3
20
+ - @learncard/encryption-plugin@1.1.38
21
+ - @learncard/learn-card-plugin@1.2.38
22
+ - @learncard/vc-plugin@1.6.4
23
+ - @learncard/vc-templates-plugin@1.1.38
24
+ - @learncard/crypto-plugin@1.1.38
25
+ - @learncard/expiration-plugin@1.2.38
26
+
27
+ ## 2.5.35
28
+
29
+ ### Patch Changes
30
+
31
+ - Updated dependencies [[`4b83aa9ee802f0d7a54adc5f053a7376fa103cdd`](https://github.com/learningeconomy/LearnCard/commit/4b83aa9ee802f0d7a54adc5f053a7376fa103cdd), [`b184f5552abf37a11468d435e5cea07fc35e1993`](https://github.com/learningeconomy/LearnCard/commit/b184f5552abf37a11468d435e5cea07fc35e1993), [`0e262737aafb8248e88e05039c83a3f30be6750f`](https://github.com/learningeconomy/LearnCard/commit/0e262737aafb8248e88e05039c83a3f30be6750f), [`d436c39e00994e6d8c77e7b94985a51fe1f42adb`](https://github.com/learningeconomy/LearnCard/commit/d436c39e00994e6d8c77e7b94985a51fe1f42adb)]:
32
+ - @learncard/types@5.22.0
33
+ - @learncard/helpers@1.6.1
34
+ - @learncard/core@9.4.37
35
+ - @learncard/did-web-plugin@1.1.37
36
+ - @learncard/didkey-plugin@1.1.37
37
+ - @learncard/didkit-plugin@1.10.2
38
+ - @learncard/didkit-plugin-node@0.3.2
39
+ - @learncard/encryption-plugin@1.1.37
40
+ - @learncard/learn-card-plugin@1.2.37
41
+ - @learncard/vc-plugin@1.6.3
42
+ - @learncard/vc-templates-plugin@1.1.37
43
+ - @learncard/crypto-plugin@1.1.37
44
+ - @learncard/expiration-plugin@1.2.37
45
+
3
46
  ## 2.5.34
4
47
 
5
48
  ### Patch Changes
@@ -0,0 +1,68 @@
1
+ import type { APIGatewayProxyEventV2, Context } from 'aws-lambda';
2
+ import { beforeEach, expect, it, vi } from 'vitest';
3
+
4
+ const mocks = vi.hoisted(() => ({ bootstrap: vi.fn(), getApp: vi.fn(), handler: vi.fn() }));
5
+
6
+ const HANDLERS = ['trpcHandler', 'openApiHandler', 'shareContentHandler', 'swaggerUiHandler'];
7
+
8
+ vi.mock('@learncard/service-config', () => ({ bootstrapLambda: mocks.bootstrap }));
9
+ vi.mock('./src/config/stageConfig', () => ({ base: {}, stages: { dev: {}, production: {} } }));
10
+ vi.mock('./lambdaApp', () => Object.fromEntries(HANDLERS.map(name => [name, mocks.handler])));
11
+
12
+ beforeEach(() => {
13
+ vi.resetModules();
14
+ vi.clearAllMocks();
15
+ mocks.bootstrap.mockReturnValue(mocks.getApp);
16
+ mocks.handler.mockResolvedValue({ statusCode: 200 });
17
+ });
18
+
19
+ it('bootstraps the API once with checked-in stage config', async () => {
20
+ vi.stubEnv('AWS_LAMBDA_FUNCTION_NAME', 'learn-cloud-service-dev-trpc');
21
+ vi.stubEnv('LAMBDA_STAGE', 'dev');
22
+ await import('./lambda');
23
+ expect(mocks.bootstrap).toHaveBeenCalledTimes(1);
24
+ expect(mocks.bootstrap).toHaveBeenCalledWith({
25
+ base: {},
26
+ stages: { dev: {}, production: {} },
27
+ stage: 'dev',
28
+ importApp: expect.any(Function),
29
+ });
30
+ vi.unstubAllEnvs();
31
+ });
32
+
33
+ it('uses CONFIG_STAGE outside Lambda rather than LAMBDA_STAGE', async () => {
34
+ vi.stubEnv('AWS_LAMBDA_FUNCTION_NAME', '');
35
+ vi.stubEnv('LAMBDA_STAGE', 'production');
36
+ vi.stubEnv('CONFIG_STAGE', 'dev');
37
+ await import('./lambda');
38
+ expect(mocks.bootstrap).toHaveBeenCalledWith(expect.objectContaining({ stage: 'dev' }));
39
+ vi.unstubAllEnvs();
40
+ });
41
+
42
+ it('forces no deployed stage when serverless-offline sets a function name with an empty LAMBDA_STAGE', async () => {
43
+ vi.stubEnv('AWS_LAMBDA_FUNCTION_NAME', 'learn-cloud-service-dev-trpc');
44
+ vi.stubEnv('LAMBDA_STAGE', '');
45
+ vi.stubEnv('CONFIG_STAGE', '');
46
+ await import('./lambda');
47
+ expect(mocks.bootstrap).toHaveBeenCalledWith(expect.objectContaining({ stage: '' }));
48
+ vi.unstubAllEnvs();
49
+ });
50
+
51
+ it('forwards every handler through its bootstrap accessor', async () => {
52
+ mocks.getApp.mockResolvedValue(Object.fromEntries(HANDLERS.map(name => [name, mocks.handler])));
53
+ const lambda = await import('./lambda');
54
+ const event = {} as APIGatewayProxyEventV2;
55
+ const context = {} as Context;
56
+ const callback = vi.fn();
57
+ const handlers = [
58
+ lambda.trpcHandler,
59
+ lambda.openApiHandler,
60
+ lambda.shareContentHandler,
61
+ lambda.swaggerUiHandler,
62
+ ];
63
+ for (const handler of handlers) await handler(event, context, callback);
64
+ expect(mocks.bootstrap).toHaveBeenCalledTimes(1);
65
+ expect(mocks.getApp).toHaveBeenCalledTimes(handlers.length);
66
+ expect(mocks.handler).toHaveBeenCalledTimes(handlers.length);
67
+ expect(mocks.handler).toHaveBeenCalledWith(event, context, callback);
68
+ });
@@ -0,0 +1,8 @@
1
+ {
2
+ "SENTRY_ENV": "learn-cloud-staging",
3
+ "SERVER_URL": "https://staging.cloud.learncard.com",
4
+ "SHARE_CONTENT_AUDIENCE": "did:web:staging.cloud.learncard.com",
5
+ "SHARE_CONTENT_NAMESPACE_BINDINGS": "{\"did:web:staging.network.learncard.com\":[\"learncard\"]}",
6
+ "SHARE_CONTENT_SERVICE_DIDS": "did:web:staging.network.learncard.com",
7
+ "SHARE_CONTENT_VERIFICATION_METHODS": "did:web:staging.network.learncard.com#owner"
8
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "SENTRY_ENV": "learn-cloud-example",
3
+ "SERVER_URL": "https://cloud.example.com",
4
+ "SHARE_CONTENT_AUDIENCE": "did:web:cloud.example.com",
5
+ "SHARE_CONTENT_NAMESPACE_BINDINGS": "{\"did:web:network.example.com\":[\"learncard\"]}",
6
+ "SHARE_CONTENT_SERVICE_DIDS": "did:web:network.example.com",
7
+ "SHARE_CONTENT_VERIFICATION_METHODS": "did:web:network.example.com#owner"
8
+ }
@@ -0,0 +1 @@
1
+ {}
@@ -0,0 +1,8 @@
1
+ {
2
+ "SENTRY_ENV": "learn-cloud-production",
3
+ "SERVER_URL": "https://cloud.learncard.com",
4
+ "SHARE_CONTENT_AUDIENCE": "did:web:cloud.learncard.com",
5
+ "SHARE_CONTENT_NAMESPACE_BINDINGS": "{\"did:web:network.learncard.com\":[\"learncard\"]}",
6
+ "SHARE_CONTENT_SERVICE_DIDS": "did:web:network.learncard.com",
7
+ "SHARE_CONTENT_VERIFICATION_METHODS": "did:web:network.learncard.com#owner"
8
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "SENTRY_ENV": "scouts-learn-cloud-staging"
3
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "SENTRY_ENV": "scouts-learn-cloud-production",
3
+ "SERVER_URL": "https://cloud.learncard.com"
4
+ }
@@ -0,0 +1,41 @@
1
+ import type { APIGatewayProxyEventV2, Context } from 'aws-lambda';
2
+ import { beforeEach, expect, it, vi } from 'vitest';
3
+
4
+ const mocks = vi.hoisted(() => ({ bootstrap: vi.fn(), getApp: vi.fn(), handler: vi.fn() }));
5
+
6
+ vi.mock('@learncard/service-config', () => ({ bootstrapLambda: mocks.bootstrap }));
7
+ vi.mock('./src/config/stageConfig', () => ({ base: {}, stages: { dev: {}, production: {} } }));
8
+ vi.mock('./didWebLambdaApp', () => ({ didWebHandler: mocks.handler }));
9
+
10
+ beforeEach(() => {
11
+ vi.resetModules();
12
+ vi.clearAllMocks();
13
+ mocks.bootstrap.mockReturnValue(mocks.getApp);
14
+ mocks.getApp.mockResolvedValue({ didWebHandler: mocks.handler });
15
+ mocks.handler.mockResolvedValue({ statusCode: 200 });
16
+ });
17
+
18
+ it('bootstraps the didWeb app with checked-in stage config and the deploy stage', async () => {
19
+ vi.stubEnv('AWS_LAMBDA_FUNCTION_NAME', 'learn-cloud-service-production-didWeb');
20
+ vi.stubEnv('LAMBDA_STAGE', 'production');
21
+ await import('./didWebLambda');
22
+ expect(mocks.bootstrap).toHaveBeenCalledTimes(1);
23
+ expect(mocks.bootstrap).toHaveBeenCalledWith({
24
+ base: {},
25
+ stages: { dev: {}, production: {} },
26
+ stage: 'production',
27
+ importApp: expect.any(Function),
28
+ });
29
+ vi.unstubAllEnvs();
30
+ });
31
+
32
+ it('resolves the app once per cold start and forwards every argument', async () => {
33
+ const { didWebHandler } = await import('./didWebLambda');
34
+ const event = {} as APIGatewayProxyEventV2;
35
+ const context = {} as Context;
36
+ const callback = vi.fn();
37
+ await didWebHandler(event, context, callback);
38
+ await didWebHandler(event, context, callback);
39
+ expect(mocks.getApp).toHaveBeenCalledTimes(2);
40
+ expect(mocks.handler).toHaveBeenLastCalledWith(event, context, callback);
41
+ });
package/didWebLambda.ts CHANGED
@@ -1,23 +1,17 @@
1
- import serverlessHttp from 'serverless-http';
2
- import * as Sentry from '@sentry/serverless';
1
+ import { bootstrapLambda } from '@learncard/service-config';
3
2
 
4
- import didWebApp from './src/dids';
5
- import { environment } from './src/config/environment';
6
- import { toServerlessApplication } from './src/helpers/serverlessApplication';
3
+ import { base, stages } from './src/config/stageConfig';
7
4
 
8
- Sentry.AWSLambda.init({
9
- dsn: environment.SENTRY_DSN,
10
- environment: environment.SENTRY_ENV,
11
- enabled: Boolean(environment.SENTRY_DSN),
12
- tracesSampleRate: 1.0,
13
- integrations: [
14
- new Sentry.Integrations.Console(),
15
- new Sentry.Integrations.Http(),
16
- new Sentry.Integrations.ContextLines(),
17
- new Sentry.Integrations.Mongo(),
18
- ],
5
+ type DidWebApp = typeof import('./didWebLambdaApp');
6
+
7
+ const getApplication = bootstrapLambda<DidWebApp>({
8
+ base,
9
+ stages,
10
+ stage: process.env.AWS_LAMBDA_FUNCTION_NAME
11
+ ? process.env.LAMBDA_STAGE
12
+ : process.env.CONFIG_STAGE,
13
+ importApp: () => import('./didWebLambdaApp'),
19
14
  });
20
15
 
21
- export const didWebHandler = Sentry.AWSLambda.wrapHandler(
22
- serverlessHttp(toServerlessApplication(didWebApp))
23
- );
16
+ export const didWebHandler = async (...args: Parameters<DidWebApp['didWebHandler']>) =>
17
+ (await getApplication()).didWebHandler(...args);
@@ -0,0 +1,23 @@
1
+ import serverlessHttp from 'serverless-http';
2
+ import * as Sentry from '@sentry/serverless';
3
+
4
+ import didWebApp from './src/dids';
5
+ import { environment } from './src/config/environment';
6
+ import { toServerlessApplication } from './src/helpers/serverlessApplication';
7
+
8
+ Sentry.AWSLambda.init({
9
+ dsn: environment.SENTRY_DSN,
10
+ environment: environment.SENTRY_ENV,
11
+ enabled: Boolean(environment.SENTRY_DSN),
12
+ tracesSampleRate: 1.0,
13
+ integrations: [
14
+ new Sentry.Integrations.Console(),
15
+ new Sentry.Integrations.Http(),
16
+ new Sentry.Integrations.ContextLines(),
17
+ new Sentry.Integrations.Mongo(),
18
+ ],
19
+ });
20
+
21
+ export const didWebHandler = Sentry.AWSLambda.wrapHandler(
22
+ serverlessHttp(toServerlessApplication(didWebApp))
23
+ );
@@ -0,0 +1,5 @@
1
+ import type { Collection } from 'mongodb';
2
+ import type { MongoShareContentDocument } from '../.././models/index';
3
+ import type { ShareContentRepositoryResult, ShareContentTombstoneSummary } from './types';
4
+ export declare const deleteShareContent: (collection: Collection<MongoShareContentDocument>, rawBinding: unknown) => Promise<ShareContentRepositoryResult<ShareContentTombstoneSummary>>;
5
+ //# sourceMappingURL=delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/share-content/delete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AAUzD,OAAO,KAAK,EAAE,4BAA4B,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAgB1F,eAAO,MAAM,kBAAkB,GAC3B,YAAY,UAAU,CAAC,yBAAyB,CAAC,EACjD,YAAY,OAAO,KACpB,OAAO,CAAC,4BAA4B,CAAC,4BAA4B,CAAC,CA4FpE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Collection, Db } from 'mongodb';
2
+ import { type MongoShareContentDocument } from '../.././models/index';
3
+ import type { ShareContentRepository } from './types';
4
+ export * from './types';
5
+ export { ensureShareContentIndexes, SHARE_CONTENT_IDENTITY_INDEX } from './initialize';
6
+ export declare const getShareContentCollection: (db: Db) => Collection<MongoShareContentDocument>;
7
+ export declare const createShareContentRepository: (collection: Collection<MongoShareContentDocument>) => ShareContentRepository;
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/share-content/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAE9C,OAAO,EAEH,KAAK,yBAAyB,EAGjC,MAAM,SAAS,CAAC;AAOjB,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEtD,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,yBAAyB,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AAOvF,eAAO,MAAM,yBAAyB,GAAI,IAAI,EAAE,KAAG,UAAU,CAAC,yBAAyB,CACjB,CAAC;AAiBvE,eAAO,MAAM,4BAA4B,GACrC,YAAY,UAAU,CAAC,yBAAyB,CAAC,KAClD,sBAyBF,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Collection } from 'mongodb';
2
+ import type { MongoShareContentDocument } from '../.././models/index';
3
+ export declare const SHARE_CONTENT_IDENTITY_INDEX = "share_content_identity_unique";
4
+ export declare const ensureShareContentIndexes: (collection: Collection<MongoShareContentDocument>) => Promise<void>;
5
+ //# sourceMappingURL=initialize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initialize.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/share-content/initialize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AAGzD,eAAO,MAAM,4BAA4B,kCAAkC,CAAC;AAW5E,eAAO,MAAM,yBAAyB,GAClC,YAAY,UAAU,CAAC,yBAAyB,CAAC,KAClD,OAAO,CAAC,IAAI,CAKd,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { Filter } from 'mongodb';
2
+ import { type MongoShareContentActive, type MongoShareContentDocument, type MongoShareContentTombstone, type ShareContentObjectBinding } from '../.././models/index';
3
+ import type { ShareContentActiveSummary, ShareContentTombstoneSummary } from './types';
4
+ export declare const MAX_SHARE_CONTENT_ATTEMPTS = 5;
5
+ export declare const parseShareContentBinding: (raw: unknown) => ShareContentObjectBinding | null;
6
+ export declare const shareContentBindingFilter: (binding: ShareContentObjectBinding) => Filter<MongoShareContentDocument>;
7
+ export declare const shareContentIdentityFilter: (binding: Pick<ShareContentObjectBinding, "namespace" | "objectId">) => Filter<MongoShareContentDocument>;
8
+ export declare const bindingMatchesDocument: (doc: MongoShareContentDocument, binding: ShareContentObjectBinding) => boolean;
9
+ export declare const isDuplicateKeyError: (error: unknown) => boolean;
10
+ export declare const toActiveSummary: (doc: MongoShareContentActive) => ShareContentActiveSummary;
11
+ export declare const toTombstoneSummary: (doc: MongoShareContentTombstone) => ShareContentTombstoneSummary;
12
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/share-content/internal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,EAEH,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EACjC,MAAM,SAAS,CAAC;AAEjB,OAAO,KAAK,EAAE,yBAAyB,EAAE,4BAA4B,EAAE,MAAM,SAAS,CAAC;AAQvF,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C,eAAO,MAAM,wBAAwB,GAAI,KAAK,OAAO,KAAG,yBAAyB,GAAG,IAInF,CAAC;AAGF,eAAO,MAAM,yBAAyB,GAClC,SAAS,yBAAyB,KACnC,MAAM,CAAC,yBAAyB,CAOjC,CAAC;AAGH,eAAO,MAAM,0BAA0B,GACnC,SAAS,IAAI,CAAC,yBAAyB,EAAE,WAAW,GAAG,UAAU,CAAC,KACnE,MAAM,CAAC,yBAAyB,CAGjC,CAAC;AAEH,eAAO,MAAM,sBAAsB,GAC/B,KAAK,yBAAyB,EAC9B,SAAS,yBAAyB,KACnC,OAMwC,CAAC;AAG5C,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,KAAG,OAC0C,CAAC;AAEhG,eAAO,MAAM,eAAe,GAAI,KAAK,uBAAuB,KAAG,yBAa7D,CAAC;AAEH,eAAO,MAAM,kBAAkB,GAC3B,KAAK,0BAA0B,KAChC,4BAUD,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Collection } from 'mongodb';
2
+ import { type MongoShareContentDocument } from '../.././models/index';
3
+ import type { ShareContentPutResult } from './types';
4
+ export declare const putShareContent: (collection: Collection<MongoShareContentDocument>, rawInput: unknown) => Promise<ShareContentPutResult>;
5
+ //# sourceMappingURL=put.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"put.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/share-content/put.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,EAMH,KAAK,yBAAyB,EAEjC,MAAM,SAAS,CAAC;AASjB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAqCrD,eAAO,MAAM,eAAe,GACxB,YAAY,UAAU,CAAC,yBAAyB,CAAC,EACjD,UAAU,OAAO,KAClB,OAAO,CAAC,qBAAqB,CAiC/B,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Collection } from 'mongodb';
2
+ import type { MongoShareContentDocument } from '../.././models/index';
3
+ import type { ShareContentContentProjection, ShareContentRecoveryProjection, ShareContentRepositoryResult, ShareContentStatProjection } from './types';
4
+ export declare const getShareContentContent: (collection: Collection<MongoShareContentDocument>, rawBinding: unknown) => Promise<ShareContentRepositoryResult<ShareContentContentProjection>>;
5
+ export declare const getShareContentRecovery: (collection: Collection<MongoShareContentDocument>, rawBinding: unknown) => Promise<ShareContentRepositoryResult<ShareContentRecoveryProjection>>;
6
+ export declare const statShareContent: (collection: Collection<MongoShareContentDocument>, rawBinding: unknown) => Promise<ShareContentRepositoryResult<ShareContentStatProjection>>;
7
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/share-content/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AAQzD,OAAO,KAAK,EACR,6BAA6B,EAC7B,8BAA8B,EAC9B,4BAA4B,EAC5B,0BAA0B,EAC7B,MAAM,SAAS,CAAC;AAQjB,eAAO,MAAM,sBAAsB,GAC/B,YAAY,UAAU,CAAC,yBAAyB,CAAC,EACjD,YAAY,OAAO,KACpB,OAAO,CAAC,4BAA4B,CAAC,6BAA6B,CAAC,CA6BrE,CAAC;AAQF,eAAO,MAAM,uBAAuB,GAChC,YAAY,UAAU,CAAC,yBAAyB,CAAC,EACjD,YAAY,OAAO,KACpB,OAAO,CAAC,4BAA4B,CAAC,8BAA8B,CAAC,CA6BtE,CAAC;AAOF,eAAO,MAAM,gBAAgB,GACzB,YAAY,UAAU,CAAC,yBAAyB,CAAC,EACjD,YAAY,OAAO,KACpB,OAAO,CAAC,4BAA4B,CAAC,0BAA0B,CAAC,CAkBlE,CAAC"}
@@ -0,0 +1,85 @@
1
+ import type { Collection } from 'mongodb';
2
+ import type { MongoShareContentDocument, ShareContentHash, ShareContentObjectBinding, ShareContentPutInput, ShareEnvelope, ShareOwnerRecovery } from '../.././models/index';
3
+ export type ShareContentRepositoryError = 'INVALID_INPUT' | 'NOT_FOUND' | 'TOMBSTONED' | 'BINDING_MISMATCH' | 'CONFLICT' | 'STORE_ERROR';
4
+ export type ShareContentRepositoryFailure = {
5
+ ok: false;
6
+ error: ShareContentRepositoryError;
7
+ };
8
+ export type ShareContentRepositoryResult<T> = {
9
+ ok: true;
10
+ value: T;
11
+ } | ShareContentRepositoryFailure;
12
+ export type ShareContentWriteStatus = 'created' | 'idempotent';
13
+ export type ShareContentActiveSummary = {
14
+ kind: 'active';
15
+ namespace: string;
16
+ ownerProfileId: string;
17
+ shareId: string;
18
+ contentVersion: number;
19
+ objectId: string;
20
+ operationId: string;
21
+ contentHash: ShareContentHash;
22
+ payloadHash: ShareContentHash;
23
+ ciphertextBytes: number;
24
+ recoveryBytes: number;
25
+ createdAt: Date;
26
+ };
27
+ export type ShareContentTombstoneSummary = {
28
+ kind: 'tombstone';
29
+ namespace: string;
30
+ ownerProfileId: string;
31
+ shareId: string;
32
+ contentVersion: number;
33
+ objectId: string;
34
+ operationId: string;
35
+ contentHash?: ShareContentHash;
36
+ deletedAt: Date;
37
+ };
38
+ export type ShareContentContentProjection = {
39
+ kind: 'active';
40
+ namespace: string;
41
+ ownerProfileId: string;
42
+ shareId: string;
43
+ contentVersion: number;
44
+ objectId: string;
45
+ operationId: string;
46
+ contentHash: ShareContentHash;
47
+ payloadHash: ShareContentHash;
48
+ envelope: ShareEnvelope;
49
+ ciphertextBytes: number;
50
+ createdAt: Date;
51
+ };
52
+ export type ShareContentRecoveryProjection = {
53
+ kind: 'active';
54
+ namespace: string;
55
+ ownerProfileId: string;
56
+ shareId: string;
57
+ contentVersion: number;
58
+ objectId: string;
59
+ operationId: string;
60
+ contentHash: ShareContentHash;
61
+ payloadHash: ShareContentHash;
62
+ ownerEncryptedRecovery: ShareOwnerRecovery;
63
+ recoveryBytes: number;
64
+ createdAt: Date;
65
+ };
66
+ export type ShareContentStatProjection = ShareContentActiveSummary | ShareContentTombstoneSummary;
67
+ export type ShareContentPutResultValue = {
68
+ status: ShareContentWriteStatus;
69
+ record: ShareContentActiveSummary;
70
+ };
71
+ export type ShareContentPutResult = ShareContentRepositoryResult<ShareContentPutResultValue>;
72
+ export type ShareContentRepository = {
73
+ readonly collection: Collection<MongoShareContentDocument>;
74
+ initialize: () => Promise<void>;
75
+ put: (input: ShareContentPutInput) => Promise<ShareContentPutResult>;
76
+ getContent: (binding: ShareContentObjectBinding) => Promise<ShareContentRepositoryResult<ShareContentContentProjection>>;
77
+ getRecovery: (binding: ShareContentObjectBinding) => Promise<ShareContentRepositoryResult<ShareContentRecoveryProjection>>;
78
+ stat: (binding: ShareContentObjectBinding) => Promise<ShareContentRepositoryResult<ShareContentStatProjection>>;
79
+ delete: (binding: ShareContentObjectBinding) => Promise<ShareContentRepositoryResult<ShareContentTombstoneSummary>>;
80
+ };
81
+ export declare class ShareContentRepositoryNotInitializedError extends Error {
82
+ readonly code = "SHARE_CONTENT_REPOSITORY_NOT_INITIALIZED";
83
+ constructor();
84
+ }
85
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/share-content/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=applyDockerStageConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"applyDockerStageConfig.d.ts","sourceRoot":"","sources":["../../src/config/applyDockerStageConfig.ts"],"names":[],"mappings":""}
@@ -37,6 +37,10 @@ export declare const learnCloudServiceEnvironmentShape: {
37
37
  true: "true";
38
38
  false: "false";
39
39
  }>, z.ZodTransform<boolean, "0" | "1" | "true" | "false">>>>>;
40
+ SHARE_CONTENT_AUDIENCE: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
41
+ SHARE_CONTENT_SERVICE_DIDS: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
42
+ SHARE_CONTENT_VERIFICATION_METHODS: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
43
+ SHARE_CONTENT_NAMESPACE_BINDINGS: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
40
44
  };
41
45
  export declare const learnCloudServiceEnvironmentSchema: z.ZodObject<{
42
46
  NODE_ENV: z.ZodDefault<z.ZodEnum<{
@@ -75,6 +79,10 @@ export declare const learnCloudServiceEnvironmentSchema: z.ZodObject<{
75
79
  true: "true";
76
80
  false: "false";
77
81
  }>, z.ZodTransform<boolean, "0" | "1" | "true" | "false">>>>>;
82
+ SHARE_CONTENT_AUDIENCE: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
83
+ SHARE_CONTENT_SERVICE_DIDS: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
84
+ SHARE_CONTENT_VERIFICATION_METHODS: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
85
+ SHARE_CONTENT_NAMESPACE_BINDINGS: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
78
86
  }, z.core.$strip>;
79
87
  export type LearnCloudServiceEnvironment = z.output<typeof learnCloudServiceEnvironmentSchema>;
80
88
  export declare const parseLearnCloudServiceEnvironment: (raw: Record<string, unknown>, source?: string) => LearnCloudServiceEnvironment;
@@ -96,5 +104,9 @@ export declare const environment: {
96
104
  REDIS_PORT?: number | undefined;
97
105
  SENTRY_DSN?: string | undefined;
98
106
  SENTRY_ENV?: string | undefined;
107
+ SHARE_CONTENT_AUDIENCE?: string | undefined;
108
+ SHARE_CONTENT_SERVICE_DIDS?: string | undefined;
109
+ SHARE_CONTENT_VERIFICATION_METHODS?: string | undefined;
110
+ SHARE_CONTENT_NAMESPACE_BINDINGS?: string | undefined;
99
111
  };
100
112
  //# sourceMappingURL=environment.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/config/environment.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAEvB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkBrB,CAAC;AAE1B,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyBzC,CAAC;AAEP,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAE/F,eAAO,MAAM,iCAAiC,GAC1C,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,eAA8B,KAC/B,4BAmBF,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;CAAiD,CAAC"}
1
+ {"version":3,"file":"environment.d.ts","sourceRoot":"","sources":["../../src/config/environment.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AAEvB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyBrB,CAAC;AAE1B,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmDzC,CAAC;AAEP,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAE/F,eAAO,MAAM,iCAAiC,GAC1C,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,eAA8B,KAC/B,4BAmBF,CAAC;AAEF,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;CAAiD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=serverlessFunctionEnv.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverlessFunctionEnv.test.d.ts","sourceRoot":"","sources":["../../src/config/serverlessFunctionEnv.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import 'dotenv/config';
2
+ export declare const base: Record<string, string>;
3
+ export declare const stages: {
4
+ dev: any;
5
+ production: any;
6
+ 'scouts.dev': any;
7
+ 'scouts.production': any;
8
+ };
9
+ export declare const applyLearnCloudStageConfig: (stage: string | undefined) => void;
10
+ //# sourceMappingURL=stageConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stageConfig.d.ts","sourceRoot":"","sources":["../../src/config/stageConfig.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AASvB,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAc,CAAC;AAEvD,eAAO,MAAM,MAAM;;;;;CAM+B,CAAC;AAInD,eAAO,MAAM,0BAA0B,GAAI,OAAO,MAAM,GAAG,SAAS,KAAG,IAEtE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=stageConfig.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stageConfig.test.d.ts","sourceRoot":"","sources":["../../src/config/stageConfig.test.ts"],"names":[],"mappings":""}
Binary file
@@ -1,2 +1,2 @@
1
- export {};
1
+ import './config/applyDockerStageConfig';
2
2
  //# sourceMappingURL=docker-entry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"docker-entry.d.ts","sourceRoot":"","sources":["../src/docker-entry.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"docker-entry.d.ts","sourceRoot":"","sources":["../src/docker-entry.ts"],"names":[],"mappings":"AAAA,OAAO,iCAAiC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { PresentationVerificationResult, PresentationVerifier, ReplayStore } from './types';
2
+ export type LearnCardLike = {
3
+ invoke: {
4
+ verifyPresentation: (token: string, options: {
5
+ proofFormat: 'jwt';
6
+ }) => Promise<PresentationVerificationResult>;
7
+ };
8
+ };
9
+ export declare const createDidkitPresentationVerifier: (getLearnCard: () => Promise<LearnCardLike>) => PresentationVerifier;
10
+ export type SetIfAbsent = (key: string, ttlSeconds: number) => Promise<boolean>;
11
+ export declare const createSetIfAbsentReplayStore: (setIfAbsent: SetIfAbsent) => ReplayStore;
12
+ //# sourceMappingURL=adapters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../../src/helpers/share-content-auth/adapters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,8BAA8B,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAWjG,MAAM,MAAM,aAAa,GAAG;IACxB,MAAM,EAAE;QACJ,kBAAkB,EAAE,CAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE;YAAE,WAAW,EAAE,KAAK,CAAA;SAAE,KAC9B,OAAO,CAAC,8BAA8B,CAAC,CAAC;KAChD,CAAC;CACL,CAAC;AASF,eAAO,MAAM,gCAAgC,GACzC,cAAc,MAAM,OAAO,CAAC,aAAa,CAAC,KAC3C,oBAMF,CAAC;AAOF,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAGhF,eAAO,MAAM,4BAA4B,GAAI,aAAa,WAAW,KAAG,WAEtE,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type ShareContentOperation } from './types';
2
+ export { canonicalizeShareContentRequestBody, DEFAULT_MAX_CANONICAL_BYTES as DEFAULT_MAX_CANONICAL_REQUEST_BYTES, DEFAULT_MAX_CANONICAL_DEPTH, ShareContentCanonicalizationError, } from '@learncard/helpers';
3
+ export declare const isPlainObject: (value: unknown) => value is Record<string, unknown>;
4
+ export declare const isCanonicalBase64Url: (value: unknown, expectedBytes?: number) => value is string;
5
+ export declare const isSafeContentVersion: (value: unknown) => value is number;
6
+ export declare const isSafeEpochSecond: (value: unknown) => value is number;
7
+ export declare const isOpaqueIdentifier: (value: unknown, maxLength?: number) => value is string;
8
+ export declare const isBoundedNonce: (value: unknown, minLength: number, maxLength: number) => value is string;
9
+ export declare const isSha256Hex: (value: unknown) => value is string;
10
+ export declare const isShareContentOperation: (value: unknown) => value is ShareContentOperation;
11
+ export declare const computeShareContentRequestHash: (body: unknown, options?: {
12
+ maxBytes?: number;
13
+ maxDepth?: number;
14
+ }) => string;
15
+ //# sourceMappingURL=canonical.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../../../src/helpers/share-content-auth/canonical.ts"],"names":[],"mappings":"AAGA,OAAO,EAA4B,KAAK,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAW/E,OAAO,EACH,mCAAmC,EACnC,2BAA2B,IAAI,mCAAmC,EAClE,2BAA2B,EAC3B,iCAAiC,GACpC,MAAM,oBAAoB,CAAC;AAO5B,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAM7E,CAAC;AAGF,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,EAAE,gBAAgB,MAAM,KAAG,KAAK,IAAI,MAUtF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MACmC,CAAC;AAEnG,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MACc,CAAC;AAM3E,eAAO,MAAM,kBAAkB,GAAI,OAAO,OAAO,EAAE,kBAAe,KAAG,KAAK,IAAI,MAI1C,CAAC;AAErC,eAAO,MAAM,cAAc,GACvB,OAAO,OAAO,EACd,WAAW,MAAM,EACjB,WAAW,MAAM,KAClB,KAAK,IAAI,MAIU,CAAC;AAEvB,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,MACI,CAAC;AAE3D,eAAO,MAAM,uBAAuB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,qBAC8B,CAAC;AAOjG,eAAO,MAAM,8BAA8B,GACvC,MAAM,OAAO,EACb,UAAS;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,KACvD,MAGmB,CAAC"}