@learncard/network-brain-service 4.1.3 → 5.0.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 +14 -0
- package/CHANGELOG.md +143 -0
- package/README.md +27 -1
- package/bootstrapLambda.test.ts +70 -32
- package/config/config.dev.json +1 -0
- package/config/config.example.json +2 -1
- package/config/config.production.json +1 -0
- package/config/config.scouts.dev.json +1 -0
- package/config/config.scouts.production.json +1 -0
- package/consentFlowDeadlineLambda.test.ts +108 -0
- package/consentFlowDeadlineLambda.ts +18 -0
- package/consentFlowDeadlineLambdaApp.ts +14 -0
- package/dist/accesslayer/boost/create.d.ts +8 -2
- package/dist/accesslayer/boost/create.d.ts.map +1 -1
- package/dist/accesslayer/campaign/audience.d.ts +4 -4
- package/dist/accesslayer/campaign/audience.d.ts.map +1 -1
- package/dist/accesslayer/campaign/create.d.ts +1 -1
- package/dist/accesslayer/campaign/create.d.ts.map +1 -1
- package/dist/accesslayer/campaign/delivery.d.ts +5 -0
- package/dist/accesslayer/campaign/delivery.d.ts.map +1 -0
- package/dist/accesslayer/campaign/dispatch.d.ts +5 -0
- package/dist/accesslayer/campaign/dispatch.d.ts.map +1 -0
- package/dist/accesslayer/campaign/dispatch.test.d.ts +2 -0
- package/dist/accesslayer/campaign/dispatch.test.d.ts.map +1 -0
- package/dist/accesslayer/campaign/email.d.ts +10 -0
- package/dist/accesslayer/campaign/email.d.ts.map +1 -0
- package/dist/accesslayer/campaign/email.test.d.ts +2 -0
- package/dist/accesslayer/campaign/email.test.d.ts.map +1 -0
- package/dist/accesslayer/campaign/preferences.d.ts +5 -0
- package/dist/accesslayer/campaign/preferences.d.ts.map +1 -0
- package/dist/accesslayer/campaign/read.d.ts.map +1 -1
- package/dist/accesslayer/campaign/test.d.ts +5 -0
- package/dist/accesslayer/campaign/test.d.ts.map +1 -0
- package/dist/accesslayer/campaign/test.test.d.ts +2 -0
- package/dist/accesslayer/campaign/test.test.d.ts.map +1 -0
- package/dist/accesslayer/campaign/update.d.ts.map +1 -1
- package/dist/accesslayer/consentflowcontract/create.d.ts.map +1 -1
- package/dist/accesslayer/consentflowcontract/delete.d.ts +1 -1
- package/dist/accesslayer/consentflowcontract/delete.d.ts.map +1 -1
- package/dist/accesslayer/consentflowcontract/read.d.ts.map +1 -1
- package/dist/accesslayer/consentflowcontract/relationships/create.d.ts +2 -1
- package/dist/accesslayer/consentflowcontract/relationships/create.d.ts.map +1 -1
- package/dist/accesslayer/consentflowcontract/relationships/read.d.ts +19 -4
- package/dist/accesslayer/consentflowcontract/relationships/read.d.ts.map +1 -1
- package/dist/accesslayer/consentflowcontract/relationships/update.d.ts +6 -1
- package/dist/accesslayer/consentflowcontract/relationships/update.d.ts.map +1 -1
- package/dist/accesslayer/consentflowcontract/versions.d.ts +68 -0
- package/dist/accesslayer/consentflowcontract/versions.d.ts.map +1 -0
- package/dist/accesslayer/credential/create.d.ts +3 -1
- package/dist/accesslayer/credential/create.d.ts.map +1 -1
- package/dist/accesslayer/credential/delete.d.ts +1 -0
- package/dist/accesslayer/credential/delete.d.ts.map +1 -1
- package/dist/accesslayer/credential/relationships/create.d.ts +15 -3
- package/dist/accesslayer/credential/relationships/create.d.ts.map +1 -1
- package/dist/accesslayer/credential/relationships/read.d.ts +2 -0
- package/dist/accesslayer/credential/relationships/read.d.ts.map +1 -1
- package/dist/accesslayer/credential/relationships/update.d.ts.map +1 -1
- package/dist/accesslayer/credential-refresh/read.d.ts +1 -0
- package/dist/accesslayer/credential-refresh/read.d.ts.map +1 -1
- package/dist/accesslayer/credential-refresh/update.d.ts.map +1 -1
- package/dist/accesslayer/inbox-credential/create.d.ts +1 -0
- package/dist/accesslayer/inbox-credential/create.d.ts.map +1 -1
- package/dist/accesslayer/inbox-credential/refresh.d.ts +7 -0
- package/dist/accesslayer/inbox-credential/refresh.d.ts.map +1 -1
- package/dist/app.d.ts +11 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/cache/app-store.caches.d.ts +61 -1
- package/dist/cache/app-store.caches.d.ts.map +1 -1
- package/dist/campaign-unsubscribe.d.ts +7 -0
- package/dist/campaign-unsubscribe.d.ts.map +1 -0
- package/dist/campaign-unsubscribe.test.d.ts +2 -0
- package/dist/campaign-unsubscribe.test.d.ts.map +1 -0
- package/dist/config/environment.d.ts +42 -0
- package/dist/config/environment.d.ts.map +1 -1
- package/dist/config/stageConfig.d.ts +4 -0
- package/dist/config/stageConfig.d.ts.map +1 -1
- package/dist/credential-refresh.d.ts.map +1 -1
- package/dist/helpers/boost.helpers.d.ts +4 -1
- package/dist/helpers/boost.helpers.d.ts.map +1 -1
- package/dist/helpers/campaign-app-origin.helpers.d.ts +2 -0
- package/dist/helpers/campaign-app-origin.helpers.d.ts.map +1 -0
- package/dist/helpers/campaign-email.helpers.d.ts +13 -0
- package/dist/helpers/campaign-email.helpers.d.ts.map +1 -0
- package/dist/helpers/campaign-notifications.helpers.d.ts +7 -0
- package/dist/helpers/campaign-notifications.helpers.d.ts.map +1 -0
- package/dist/helpers/campaign-queue.helpers.d.ts +7 -0
- package/dist/helpers/campaign-queue.helpers.d.ts.map +1 -0
- package/dist/helpers/campaign-queue.helpers.test.d.ts +2 -0
- package/dist/helpers/campaign-queue.helpers.test.d.ts.map +1 -0
- package/dist/helpers/campaign-unsubscribe-page.d.ts +2 -0
- package/dist/helpers/campaign-unsubscribe-page.d.ts.map +1 -0
- package/dist/helpers/campaign-unsubscribe.helpers.d.ts +7 -0
- package/dist/helpers/campaign-unsubscribe.helpers.d.ts.map +1 -0
- package/dist/helpers/campaign-webhook.helpers.test.d.ts +2 -0
- package/dist/helpers/campaign-webhook.helpers.test.d.ts.map +1 -0
- package/dist/helpers/consentflow-deadline.helpers.d.ts +5 -0
- package/dist/helpers/consentflow-deadline.helpers.d.ts.map +1 -0
- package/dist/helpers/consentflow-legacy-migration.helpers.d.ts +2 -0
- package/dist/helpers/consentflow-legacy-migration.helpers.d.ts.map +1 -0
- package/dist/helpers/contract-events.helpers.d.ts.map +1 -1
- package/dist/helpers/contract.helpers.d.ts +1 -1
- package/dist/helpers/contract.helpers.d.ts.map +1 -1
- package/dist/helpers/credential-display.helpers.d.ts +5 -0
- package/dist/helpers/credential-display.helpers.d.ts.map +1 -0
- package/dist/helpers/credential-display.helpers.test.d.ts +2 -0
- package/dist/helpers/credential-display.helpers.test.d.ts.map +1 -0
- package/dist/helpers/credential-refresh-email.helpers.d.ts.map +1 -1
- package/dist/helpers/credential-refresh-materiality.helpers.d.ts +4 -0
- package/dist/helpers/credential-refresh-materiality.helpers.d.ts.map +1 -1
- package/dist/helpers/credential-refresh.helpers.d.ts +30 -1
- package/dist/helpers/credential-refresh.helpers.d.ts.map +1 -1
- package/dist/helpers/credential-status-mutation.helpers.d.ts +5 -0
- package/dist/helpers/credential-status-mutation.helpers.d.ts.map +1 -0
- package/dist/helpers/credential-status-mutation.helpers.test.d.ts +2 -0
- package/dist/helpers/credential-status-mutation.helpers.test.d.ts.map +1 -0
- package/dist/helpers/credential.helpers.d.ts +1 -1
- package/dist/helpers/credential.helpers.d.ts.map +1 -1
- package/dist/helpers/inbox-refresh.helpers.d.ts +4 -2
- package/dist/helpers/inbox-refresh.helpers.d.ts.map +1 -1
- package/dist/helpers/inbox.helpers.d.ts +1 -0
- package/dist/helpers/inbox.helpers.d.ts.map +1 -1
- package/dist/helpers/learnCard.helpers.d.ts +1 -0
- package/dist/helpers/learnCard.helpers.d.ts.map +1 -1
- package/dist/helpers/managed-status.helpers.d.ts +7 -0
- package/dist/helpers/managed-status.helpers.d.ts.map +1 -0
- package/dist/helpers/managed-status.helpers.test.d.ts +2 -0
- package/dist/helpers/managed-status.helpers.test.d.ts.map +1 -0
- package/dist/helpers/notification-delivery-boundary.helpers.test.d.ts +2 -0
- package/dist/helpers/notification-delivery-boundary.helpers.test.d.ts.map +1 -0
- package/dist/helpers/notification-webhook-fetch.helpers.d.ts +13 -0
- package/dist/helpers/notification-webhook-fetch.helpers.d.ts.map +1 -0
- package/dist/helpers/notification-webhook-fetch.helpers.test.d.ts +2 -0
- package/dist/helpers/notification-webhook-fetch.helpers.test.d.ts.map +1 -0
- package/dist/helpers/notificationQueue.helpers.d.ts.map +1 -1
- package/dist/helpers/notifications.helpers.d.ts.map +1 -1
- package/dist/helpers/refresh-send-intent.helpers.d.ts +13 -5
- package/dist/helpers/refresh-send-intent.helpers.d.ts.map +1 -1
- package/dist/helpers/refresh-send-intent.helpers.test.d.ts +2 -0
- package/dist/helpers/refresh-send-intent.helpers.test.d.ts.map +1 -0
- package/dist/helpers/send-contract.helpers.d.ts +11 -0
- package/dist/helpers/send-contract.helpers.d.ts.map +1 -0
- package/dist/helpers/status-list.helpers.d.ts +12 -1
- package/dist/helpers/status-list.helpers.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/models/ConsentFlowContract.d.ts.map +1 -1
- package/dist/models/ConsentFlowContractVersion.d.ts +12 -0
- package/dist/models/ConsentFlowContractVersion.d.ts.map +1 -0
- package/dist/models/ConsentFlowTerms.d.ts.map +1 -1
- package/dist/models/Credential.d.ts +2 -0
- package/dist/models/Credential.d.ts.map +1 -1
- package/dist/models/CredentialRefresh.d.ts +5 -0
- package/dist/models/CredentialRefresh.d.ts.map +1 -1
- package/dist/models/Integration.d.ts +1 -1
- package/dist/models/Profile.d.ts.map +1 -1
- package/dist/models/campaign-constraints.d.ts.map +1 -1
- package/dist/models/index.d.ts +1 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/openapi.d.ts.map +1 -1
- package/dist/publish-metafile.json +1 -1
- package/dist/routes/activity.d.ts +15 -5
- package/dist/routes/activity.d.ts.map +1 -1
- package/dist/routes/app-store.d.ts +15 -5
- package/dist/routes/app-store.d.ts.map +1 -1
- package/dist/routes/auth-grants.d.ts +12 -2
- package/dist/routes/auth-grants.d.ts.map +1 -1
- package/dist/routes/bench.d.ts +11 -1
- package/dist/routes/bench.d.ts.map +1 -1
- package/dist/routes/boosts.d.ts +70 -15
- package/dist/routes/boosts.d.ts.map +1 -1
- package/dist/routes/campaigns.d.ts +183 -51
- package/dist/routes/campaigns.d.ts.map +1 -1
- package/dist/routes/claim-hooks.d.ts +11 -1
- package/dist/routes/claim-hooks.d.ts.map +1 -1
- package/dist/routes/contact-methods.d.ts +11 -1
- package/dist/routes/contact-methods.d.ts.map +1 -1
- package/dist/routes/contracts.d.ts +374 -8
- package/dist/routes/contracts.d.ts.map +1 -1
- package/dist/routes/credential-input-privacy.test.d.ts +2 -0
- package/dist/routes/credential-input-privacy.test.d.ts.map +1 -0
- package/dist/routes/credential-refreshes.d.ts +210 -1
- package/dist/routes/credential-refreshes.d.ts.map +1 -1
- package/dist/routes/credential-share-previews.d.ts +11 -1
- package/dist/routes/credential-share-previews.d.ts.map +1 -1
- package/dist/routes/credentials.d.ts +132 -3
- package/dist/routes/credentials.d.ts.map +1 -1
- package/dist/routes/did-metadata.d.ts +11 -1
- package/dist/routes/did-metadata.d.ts.map +1 -1
- package/dist/routes/federation.d.ts +11 -1
- package/dist/routes/federation.d.ts.map +1 -1
- package/dist/routes/inbox.d.ts +54 -19
- package/dist/routes/inbox.d.ts.map +1 -1
- package/dist/routes/index.d.ts +100 -1
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/integrations.d.ts +14 -4
- package/dist/routes/integrations.d.ts.map +1 -1
- package/dist/routes/presentations.d.ts +11 -1
- package/dist/routes/presentations.d.ts.map +1 -1
- package/dist/routes/profile-manager.d.ts +11 -1
- package/dist/routes/profile-manager.d.ts.map +1 -1
- package/dist/routes/profiles.d.ts +11 -1
- package/dist/routes/profiles.d.ts.map +1 -1
- package/dist/routes/public-share-links.d.ts +22 -2
- package/dist/routes/public-share-links.d.ts.map +1 -1
- package/dist/routes/share-links.d.ts +36 -16
- package/dist/routes/share-links.d.ts.map +1 -1
- package/dist/routes/skill-frameworks.d.ts +11 -1
- package/dist/routes/skill-frameworks.d.ts.map +1 -1
- package/dist/routes/skills.d.ts +11 -1
- package/dist/routes/skills.d.ts.map +1 -1
- package/dist/routes/storage.d.ts +37 -23
- package/dist/routes/storage.d.ts.map +1 -1
- package/dist/routes/test.d.ts +79 -3
- package/dist/routes/test.d.ts.map +1 -1
- package/dist/routes/utilities.d.ts +11 -1
- package/dist/routes/utilities.d.ts.map +1 -1
- package/dist/routes/workflows.d.ts +11 -1
- package/dist/routes/workflows.d.ts.map +1 -1
- package/dist/services/delivery/adapters/postmark.adapter.d.ts +3 -0
- package/dist/services/delivery/adapters/postmark.adapter.d.ts.map +1 -1
- package/dist/services/delivery/delivery.service.d.ts +10 -0
- package/dist/services/delivery/delivery.service.d.ts.map +1 -1
- package/dist/types/activity.d.ts +3 -3
- package/dist/types/app-manifest.d.ts +10 -10
- package/dist/types/campaign.d.ts +13 -1
- package/dist/types/campaign.d.ts.map +1 -1
- package/dist/types/consentflowcontract.d.ts +175 -7
- package/dist/types/consentflowcontract.d.ts.map +1 -1
- package/dist/types/credential-refresh.d.ts +27 -0
- package/dist/types/credential-refresh.d.ts.map +1 -1
- package/dist/types/credential.d.ts +5 -0
- package/dist/types/credential.d.ts.map +1 -1
- package/dist/types/integration.d.ts +3 -3
- package/lambda.ts +44 -14
- package/lambdaApp.ts +20 -0
- package/package.json +20 -19
- package/project.json +5 -0
- package/scripts/migrate-consent-flow-versions.ts +9 -0
- package/scripts/report-send-template-exposure.ts +47 -0
- package/scripts/verify-python-contracts.ts +16 -1
- package/serverless-local.yml +15 -2
- package/serverless.function-env.cjs +4 -0
- package/serverless.local.yml +12 -0
- package/serverless.yml +48 -3
- package/src/accesslayer/boost/create.ts +62 -7
- package/src/accesslayer/campaign/README.md +275 -6
- package/src/accesslayer/campaign/audience.ts +39 -7
- package/src/accesslayer/campaign/create.ts +4 -2
- package/src/accesslayer/campaign/delivery.ts +66 -0
- package/src/accesslayer/campaign/dispatch.test.ts +59 -0
- package/src/accesslayer/campaign/dispatch.ts +172 -0
- package/src/accesslayer/campaign/email.test.ts +73 -0
- package/src/accesslayer/campaign/email.ts +91 -0
- package/src/accesslayer/campaign/preferences.ts +53 -0
- package/src/accesslayer/campaign/read.ts +3 -1
- package/src/accesslayer/campaign/state.ts +1 -1
- package/src/accesslayer/campaign/test.test.ts +31 -0
- package/src/accesslayer/campaign/test.ts +75 -0
- package/src/accesslayer/campaign/update.ts +15 -4
- package/src/accesslayer/consentflowcontract/create.ts +20 -1
- package/src/accesslayer/consentflowcontract/delete.ts +121 -3
- package/src/accesslayer/consentflowcontract/read.ts +15 -9
- package/src/accesslayer/consentflowcontract/relationships/create.ts +70 -36
- package/src/accesslayer/consentflowcontract/relationships/read.ts +305 -73
- package/src/accesslayer/consentflowcontract/relationships/smartResume.ts +1 -1
- package/src/accesslayer/consentflowcontract/relationships/update.ts +269 -98
- package/src/accesslayer/consentflowcontract/versions.ts +790 -0
- package/src/accesslayer/credential/create.ts +33 -9
- package/src/accesslayer/credential/delete.ts +45 -0
- package/src/accesslayer/credential/relationships/create.ts +102 -47
- package/src/accesslayer/credential/relationships/update.ts +8 -116
- package/src/accesslayer/credential-refresh/read.ts +26 -2
- package/src/accesslayer/credential-refresh/update.ts +6 -2
- package/src/accesslayer/inbox-credential/create.ts +7 -1
- package/src/accesslayer/inbox-credential/refresh.ts +14 -4
- package/src/campaign-unsubscribe.test.ts +158 -0
- package/src/campaign-unsubscribe.ts +86 -0
- package/src/config/environment.test.ts +52 -0
- package/src/config/environment.ts +58 -0
- package/src/config/serverlessFunctionEnv.test.ts +59 -0
- package/src/credential-refresh.ts +1 -0
- package/src/docker-entry.ts +26 -1
- package/src/helpers/boost-storage.helpers.test.ts +107 -41
- package/src/helpers/boost.helpers.ts +88 -40
- package/src/helpers/campaign-app-origin.helpers.ts +25 -0
- package/src/helpers/campaign-email.helpers.ts +113 -0
- package/src/helpers/campaign-notifications.helpers.ts +127 -0
- package/src/helpers/campaign-queue.helpers.test.ts +442 -0
- package/src/helpers/campaign-queue.helpers.ts +122 -0
- package/src/helpers/campaign-unsubscribe-page.ts +107 -0
- package/src/helpers/campaign-unsubscribe.helpers.ts +56 -0
- package/src/helpers/campaign-webhook.helpers.test.ts +137 -0
- package/src/helpers/consentflow-deadline.helpers.ts +22 -0
- package/src/helpers/consentflow-legacy-migration.helpers.ts +179 -0
- package/src/helpers/contract-events.helpers.ts +35 -3
- package/src/helpers/contract-requests.helpers.ts +1 -1
- package/src/helpers/contract.helpers.ts +5 -1
- package/src/helpers/credential-display.helpers.test.ts +68 -0
- package/src/helpers/credential-display.helpers.ts +15 -0
- package/src/helpers/credential-refresh-email.helpers.ts +5 -12
- package/src/helpers/credential-refresh-materiality.helpers.test.ts +138 -1
- package/src/helpers/credential-refresh-materiality.helpers.ts +62 -1
- package/src/helpers/credential-refresh-proof.helpers.test.ts +1 -1
- package/src/helpers/credential-refresh-proof.helpers.ts +2 -2
- package/src/helpers/credential-refresh.helpers.ts +1166 -376
- package/src/helpers/credential-status-mutation.helpers.test.ts +155 -0
- package/src/helpers/credential-status-mutation.helpers.ts +166 -0
- package/src/helpers/credential.helpers.ts +19 -11
- package/src/helpers/finalize-inbox.helpers.ts +1 -1
- package/src/helpers/inbox-refresh.helpers.ts +34 -8
- package/src/helpers/inbox.helpers.ts +2 -0
- package/src/helpers/learnCard.helpers.ts +23 -0
- package/src/helpers/managed-status.helpers.test.ts +101 -0
- package/src/helpers/managed-status.helpers.ts +147 -0
- package/src/helpers/notification-delivery-boundary.helpers.test.ts +114 -0
- package/src/helpers/notification-webhook-fetch.helpers.test.ts +228 -0
- package/src/helpers/notification-webhook-fetch.helpers.ts +166 -0
- package/src/helpers/notificationQueue.helpers.ts +5 -0
- package/src/helpers/notifications.helpers.ts +19 -12
- package/src/helpers/refresh-send-intent.helpers.test.ts +60 -0
- package/src/helpers/refresh-send-intent.helpers.ts +81 -18
- package/src/helpers/send-contract.helpers.ts +36 -0
- package/src/helpers/status-list.helpers.test.ts +29 -12
- package/src/helpers/status-list.helpers.ts +329 -20
- package/src/models/ConsentFlowContract.ts +3 -0
- package/src/models/ConsentFlowContractVersion.ts +50 -0
- package/src/models/ConsentFlowTerms.ts +4 -0
- package/src/models/Credential.ts +2 -0
- package/src/models/CredentialRefresh.ts +2 -0
- package/src/models/Profile.ts +2 -0
- package/src/models/campaign-constraints.ts +13 -8
- package/src/models/index.ts +2 -0
- package/src/openapi.ts +21 -0
- package/src/routes/app-store.ts +2 -1
- package/src/routes/boosts.ts +219 -137
- package/src/routes/campaigns.ts +98 -19
- package/src/routes/contracts.ts +433 -115
- package/src/routes/credential-input-privacy.test.ts +92 -0
- package/src/routes/credential-refreshes.ts +273 -2
- package/src/routes/federation.ts +7 -2
- package/src/routes/inbox.ts +6 -1
- package/src/routes/index.ts +31 -2
- package/src/routes/workflows.ts +61 -46
- package/src/services/delivery/adapters/postmark.adapter.test.ts +70 -1
- package/src/services/delivery/adapters/postmark.adapter.ts +84 -11
- package/src/services/delivery/delivery.service.ts +4 -0
- package/src/types/campaign.ts +14 -1
- package/src/types/consentflowcontract.ts +43 -2
- package/src/types/credential-refresh.ts +11 -1
- package/src/types/credential.ts +2 -0
- package/test/boost-status-cleanup.spec.ts +123 -0
- package/test/campaigns-email.unit.spec.ts +268 -0
- package/test/campaigns.spec.ts +804 -30
- package/test/consent-autoboost-idempotency.spec.ts +432 -0
- package/test/consent-data-boundaries.spec.ts +322 -26
- package/test/consent-legacy-migration.spec.ts +315 -0
- package/test/consent-recipients.spec.ts +7 -7
- package/test/consent-version-updates.spec.ts +761 -0
- package/test/consentflow.spec.ts +698 -226
- package/test/contract-requests.spec.ts +55 -9
- package/test/credential-refresh-allocation.spec.ts +212 -14
- package/test/credential-refresh-email.spec.ts +6 -10
- package/test/credential-refresh-endpoint.spec.ts +3 -0
- package/test/credential-refresh-publication.spec.ts +52 -15
- package/test/credential-storage.neo4j.spec.ts +33 -6
- package/test/helpers/legacy-autoboost.ts +48 -0
- package/test/holder-mode-send.spec.ts +710 -0
- package/test/inbox-refresh.spec.ts +105 -0
- package/test/inbox-security.e2e.ts +18 -22
- package/test/managed-status-revocation.spec.ts +970 -0
- package/test/notifications-worker.spec.ts +31 -25
- package/test/refresh-send.spec.ts +334 -5
- package/test/smart-resume-consent.spec.ts +1 -1
- package/test/verification/campaigns.ts +40 -0
- package/vitest.campaigns.config.ts +2 -0
- package/vitest.config.ts +14 -0
|
@@ -119,6 +119,52 @@ beforeEach(async () => {
|
|
|
119
119
|
});
|
|
120
120
|
|
|
121
121
|
describe('managed Universal Inbox refresh', () => {
|
|
122
|
+
it('retries keyed issuance across retained digest key rotation', async () => {
|
|
123
|
+
try {
|
|
124
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_SECRET', 'old-inbox-test-key');
|
|
125
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_KEY_VERSION', 'v1');
|
|
126
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_PREVIOUS_KEYS', '{}');
|
|
127
|
+
const first = await issue({ idempotencyKey: 'rotation-issue' });
|
|
128
|
+
const readDigest = async () =>
|
|
129
|
+
(
|
|
130
|
+
await neogma.queryRunner.run(
|
|
131
|
+
'MATCH (ic:InboxCredential {id: $id}) RETURN ic.refreshRequestDigest AS digest',
|
|
132
|
+
{ id: first.issuanceId }
|
|
133
|
+
)
|
|
134
|
+
).records[0]!.get('digest');
|
|
135
|
+
const stored = await readDigest();
|
|
136
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_SECRET', 'new-inbox-test-key');
|
|
137
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_KEY_VERSION', 'v2');
|
|
138
|
+
vi.stubEnv(
|
|
139
|
+
'CREDENTIAL_REFRESH_DIGEST_PREVIOUS_KEYS',
|
|
140
|
+
JSON.stringify({ v1: 'old-inbox-test-key' })
|
|
141
|
+
);
|
|
142
|
+
expect(await issue({ idempotencyKey: 'rotation-issue' })).toEqual(first);
|
|
143
|
+
expect(await readDigest()).toBe(stored);
|
|
144
|
+
// Resume before claim-link persistence to exercise the atomic create/reuse check.
|
|
145
|
+
await neogma.queryRunner.run(
|
|
146
|
+
'MATCH (ic:InboxCredential {id: $id}) REMOVE ic.refreshClaimUrl',
|
|
147
|
+
{ id: first.issuanceId }
|
|
148
|
+
);
|
|
149
|
+
const resumed = await issue({ idempotencyKey: 'rotation-issue' });
|
|
150
|
+
expect(resumed.issuanceId).toBe(first.issuanceId);
|
|
151
|
+
expect(resumed.refresh).toEqual(first.refresh);
|
|
152
|
+
expect(await readDigest()).toBe(stored);
|
|
153
|
+
await expect(
|
|
154
|
+
issue({
|
|
155
|
+
idempotencyKey: 'rotation-issue',
|
|
156
|
+
credential: { ...template(), name: 'Different' },
|
|
157
|
+
})
|
|
158
|
+
).rejects.toMatchObject({ code: 'CONFLICT' });
|
|
159
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_PREVIOUS_KEYS', '{}');
|
|
160
|
+
await expect(issue({ idempotencyKey: 'rotation-issue' })).rejects.toMatchObject({
|
|
161
|
+
code: 'CONFLICT',
|
|
162
|
+
});
|
|
163
|
+
} finally {
|
|
164
|
+
vi.unstubAllEnvs();
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
122
168
|
it.each(['email', 'phone'] as const)(
|
|
123
169
|
'allocates for unknown %s, claims latest, then publishes normally',
|
|
124
170
|
async type => {
|
|
@@ -362,6 +408,46 @@ describe('managed Universal Inbox refresh', () => {
|
|
|
362
408
|
).rejects.toMatchObject({ code: 'CONFLICT' });
|
|
363
409
|
});
|
|
364
410
|
|
|
411
|
+
it('retries unified inbox send across retained digest key rotation', async () => {
|
|
412
|
+
try {
|
|
413
|
+
await issuer.clients.fullAuth.profile.setPrimarySigningAuthority(SA);
|
|
414
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_SECRET', 'old-inbox-send-test-key');
|
|
415
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_KEY_VERSION', 'v1');
|
|
416
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_PREVIOUS_KEYS', '{}');
|
|
417
|
+
const input = {
|
|
418
|
+
type: 'boost' as const,
|
|
419
|
+
recipient: 'unknown@example.com',
|
|
420
|
+
template: { credential: template() },
|
|
421
|
+
refresh: true,
|
|
422
|
+
idempotencyKey: 'rotation-unified-key',
|
|
423
|
+
options: { suppressDelivery: true },
|
|
424
|
+
};
|
|
425
|
+
const first = await issuer.clients.fullAuth.boost.send(input);
|
|
426
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_SECRET', 'new-inbox-send-test-key');
|
|
427
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_KEY_VERSION', 'v2');
|
|
428
|
+
vi.stubEnv(
|
|
429
|
+
'CREDENTIAL_REFRESH_DIGEST_PREVIOUS_KEYS',
|
|
430
|
+
JSON.stringify({ v1: 'old-inbox-send-test-key' })
|
|
431
|
+
);
|
|
432
|
+
expect(await issuer.clients.fullAuth.boost.send(input)).toEqual(first);
|
|
433
|
+
await expect(
|
|
434
|
+
issuer.clients.fullAuth.boost.send({ ...input, recipient: 'different@example.com' })
|
|
435
|
+
).rejects.toMatchObject({ code: 'CONFLICT' });
|
|
436
|
+
for (const label of ['Boost', 'InboxCredential', 'CredentialRefresh']) {
|
|
437
|
+
const count = await neogma.queryRunner.run(
|
|
438
|
+
`MATCH (n:${label}) RETURN count(n) AS count`
|
|
439
|
+
);
|
|
440
|
+
expect(Number(count.records[0]!.get('count'))).toBe(1);
|
|
441
|
+
}
|
|
442
|
+
vi.stubEnv('CREDENTIAL_REFRESH_DIGEST_PREVIOUS_KEYS', '{}');
|
|
443
|
+
await expect(issuer.clients.fullAuth.boost.send(input)).rejects.toMatchObject({
|
|
444
|
+
code: 'CONFLICT',
|
|
445
|
+
});
|
|
446
|
+
} finally {
|
|
447
|
+
vi.unstubAllEnvs();
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
|
|
365
451
|
it('retains escrow when signing fails and can retry the same claim', async () => {
|
|
366
452
|
const issued = await issue();
|
|
367
453
|
mocks.sign.mockRejectedValueOnce(new Error('Authority unavailable'));
|
|
@@ -430,6 +516,25 @@ describe('managed Universal Inbox refresh', () => {
|
|
|
430
516
|
).toBeTruthy();
|
|
431
517
|
});
|
|
432
518
|
|
|
519
|
+
it('keeps stored public names on pending publication without copying the private VC name', async () => {
|
|
520
|
+
const issued = await issue();
|
|
521
|
+
const refreshId = issued.refresh!.refreshId;
|
|
522
|
+
await neogma.queryRunner.run(
|
|
523
|
+
`MATCH (refresh:CredentialRefresh {refreshId: $refreshId})-[:INBOX]->(ic:InboxCredential)
|
|
524
|
+
SET ic.credentialName = 'Stored label', refresh.credentialDisplayName = 'Stored label'`,
|
|
525
|
+
{ refreshId }
|
|
526
|
+
);
|
|
527
|
+
await queue(issued, 'Private Updated Name');
|
|
528
|
+
const rows = await neogma.queryRunner.run(
|
|
529
|
+
`MATCH (refresh:CredentialRefresh {refreshId: $refreshId})-[:INBOX]->(ic:InboxCredential)
|
|
530
|
+
RETURN ic.credentialName AS inboxName, refresh.credentialDisplayName AS displayName`,
|
|
531
|
+
{ refreshId }
|
|
532
|
+
);
|
|
533
|
+
expect(rows.records[0]!.get('inboxName')).toBe('Stored label');
|
|
534
|
+
expect(rows.records[0]!.get('displayName')).toBe('Stored label');
|
|
535
|
+
expect((await getCredentialRefresh(refreshId))?.currentVersion).toBe(2);
|
|
536
|
+
});
|
|
537
|
+
|
|
433
538
|
it('concurrent pending publications with one key create one revision', async () => {
|
|
434
539
|
const issued = await issue();
|
|
435
540
|
const outcomes = await Promise.all([
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
2
|
import Fastify, { type FastifyInstance } from 'fastify';
|
|
3
3
|
import { fastifyTRPCOpenApiPlugin } from 'trpc-to-openapi';
|
|
4
|
-
import { readFile } from 'node:fs/promises';
|
|
5
4
|
import { randomUUID } from 'node:crypto';
|
|
6
5
|
import {
|
|
7
6
|
JWEValidator,
|
|
@@ -311,12 +310,15 @@ describe('Universal Inbox escrow (HTTP + isolated Neo4j/Redis)', () => {
|
|
|
311
310
|
const store = credentialStorage.storeCredential;
|
|
312
311
|
const storeSpy = vi
|
|
313
312
|
.spyOn(credentialStorage, 'storeCredential')
|
|
314
|
-
.mockImplementation(async payload => {
|
|
315
|
-
expect(
|
|
316
|
-
|
|
317
|
-
|
|
313
|
+
.mockImplementation(async (payload, transaction, ownerProfileId) => {
|
|
314
|
+
expect(transaction).toBeDefined();
|
|
315
|
+
const result = await transaction!.run(
|
|
316
|
+
'MATCH (n:InboxCredential {id: $id}) RETURN n.currentStatus AS status',
|
|
317
|
+
{ id: issued.issuanceId }
|
|
318
|
+
);
|
|
319
|
+
expect(result.records[0]?.get('status')).toBe('ISSUED');
|
|
318
320
|
if (outcome === 'storage failure') throw new Error('Storage unavailable');
|
|
319
|
-
return store(payload);
|
|
321
|
+
return store(payload, transaction, ownerProfileId);
|
|
320
322
|
});
|
|
321
323
|
if (outcome === 'lost race') {
|
|
322
324
|
// Another request wins after this request has read the pending payload.
|
|
@@ -336,7 +338,7 @@ describe('Universal Inbox escrow (HTTP + isolated Neo4j/Redis)', () => {
|
|
|
336
338
|
}
|
|
337
339
|
|
|
338
340
|
expect(await claim(issued.claimUrl!)).toEqual(
|
|
339
|
-
outcome === '
|
|
341
|
+
outcome === 'success' ? [credential] : []
|
|
340
342
|
);
|
|
341
343
|
expect(storeSpy).toHaveBeenCalledTimes(outcome === 'lost race' ? 0 : 1);
|
|
342
344
|
const stored = await neogma.queryRunner.run(
|
|
@@ -348,7 +350,15 @@ describe('Universal Inbox escrow (HTTP + isolated Neo4j/Redis)', () => {
|
|
|
348
350
|
'MATCH ()-[r:CLAIMED_INBOX_CREDENTIAL]->(n:InboxCredential {id: $id}) RETURN count(r) AS count',
|
|
349
351
|
{ id: issued.issuanceId }
|
|
350
352
|
);
|
|
351
|
-
expect(audit.records[0]!.get('count').toNumber()).toBe(outcome === '
|
|
353
|
+
expect(audit.records[0]!.get('count').toNumber()).toBe(outcome === 'success' ? 1 : 0);
|
|
354
|
+
if (outcome === 'storage failure') {
|
|
355
|
+
expect(await getRecord(issued.issuanceId)).toMatchObject({
|
|
356
|
+
currentStatus: 'PENDING',
|
|
357
|
+
});
|
|
358
|
+
storeSpy.mockRestore();
|
|
359
|
+
expect(await claim(issued.claimUrl!)).toEqual([credential]);
|
|
360
|
+
await expectStoredStatus(credential);
|
|
361
|
+
}
|
|
352
362
|
}
|
|
353
363
|
);
|
|
354
364
|
|
|
@@ -898,18 +908,4 @@ describe('Universal Inbox escrow (HTTP + isolated Neo4j/Redis)', () => {
|
|
|
898
908
|
currentStatus: 'EXPIRED',
|
|
899
909
|
});
|
|
900
910
|
});
|
|
901
|
-
|
|
902
|
-
it('wires the maintenance worker to an enabled daily schedule', async () => {
|
|
903
|
-
const config = await readFile(new URL('../serverless.yml', import.meta.url), 'utf8');
|
|
904
|
-
expect(config).toMatch(
|
|
905
|
-
/inboxMaintenance:\s+handler: lambda\.inboxMaintenanceHandler[\s\S]*?rate: rate\(1 day\)\s+enabled: true/
|
|
906
|
-
);
|
|
907
|
-
// lambda.ts is a thin bootstrap entry that delegates to the lazily imported lambdaApp.ts.
|
|
908
|
-
const entry = await readFile(new URL('../lambda.ts', import.meta.url), 'utf8');
|
|
909
|
-
expect(entry).toMatch(
|
|
910
|
-
/export const inboxMaintenanceHandler[\s\S]*?\(await getApplication\(\)\)\.inboxMaintenanceHandler\(/
|
|
911
|
-
);
|
|
912
|
-
const handler = await readFile(new URL('../lambdaApp.ts', import.meta.url), 'utf8');
|
|
913
|
-
expect(handler).toMatch(/inboxMaintenanceHandler[\s\S]*?await runInboxMaintenance\(\)/);
|
|
914
|
-
});
|
|
915
911
|
});
|