@learncard/network-brain-service 4.1.2 → 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 +164 -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
package/.env.example
CHANGED
|
@@ -16,6 +16,13 @@ NEO4J_PASSWORD=this-is-the-password
|
|
|
16
16
|
|
|
17
17
|
# Optional integration credentials; all are bundle/fallback-only in Lambda.
|
|
18
18
|
POSTMARK_API_KEY=
|
|
19
|
+
# Campaign email: deployed values come from LearnCard Runtime /learncard/brain-service/runtime.
|
|
20
|
+
# Stream ID is non-secret; the dedicated signing secret must be stable and at least 32 bytes.
|
|
21
|
+
# Local/Docker reads this .env; runtime bundle changes require recycling Lambda functions.
|
|
22
|
+
POSTMARK_BROADCAST_STREAM=broadcast
|
|
23
|
+
CAMPAIGN_UNSUBSCRIBE_SECRET=
|
|
24
|
+
# Deployment-owned browser origins for campaign CTAs. Hosted defaults live in stage config.
|
|
25
|
+
CAMPAIGN_APP_ORIGINS={"learncard":"http://localhost:3000"}
|
|
19
26
|
MESSAGEBIRD_AUTH_TOKEN=
|
|
20
27
|
SENTRY_DSN=
|
|
21
28
|
POSTHOG_API_KEY=
|
|
@@ -32,6 +39,13 @@ LOGIN_PROVIDER_DID=
|
|
|
32
39
|
NOTIFICATIONS_SERVICE_WEBHOOK_URL=
|
|
33
40
|
# Both checked-in stages enable credential refresh. Use independent, stable private secrets.
|
|
34
41
|
CREDENTIAL_REFRESH_DIGEST_SECRET=local-only-replace-before-deploy-refresh-digest-secret
|
|
42
|
+
# Rotate SECRET and KEY_VERSION together; retain the old secret keyed by its old version:
|
|
43
|
+
# CREDENTIAL_REFRESH_DIGEST_PREVIOUS_KEYS='{"v1":"old-secret"}' with KEY_VERSION=v2.
|
|
44
|
+
# Keep previous keys until affected aggregates republish, and longer while original
|
|
45
|
+
# subject/status/root fingerprints still reference them (publication does not rewrite those).
|
|
46
|
+
# Notification route/delivery keys also rotate, which may yield one duplicate notification.
|
|
47
|
+
CREDENTIAL_REFRESH_DIGEST_KEY_VERSION=v1
|
|
48
|
+
CREDENTIAL_REFRESH_DIGEST_PREVIOUS_KEYS={}
|
|
35
49
|
SHARE_LINK_REQUEST_HASH_SECRET=local-only-replace-before-deploy-share-link-request-secret
|
|
36
50
|
|
|
37
51
|
# Skill embeddings (LC-2206): Amazon Nova 2 Multimodal Embeddings on Bedrock via SigV4 with
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,169 @@
|
|
|
1
1
|
# @learncard/network-brain-service
|
|
2
2
|
|
|
3
|
+
## 5.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [#1819](https://github.com/learningeconomy/LearnCard/pull/1819) [`784f0c9b346a5f7e4e2c618a9b976dcaa90fafe3`](https://github.com/learningeconomy/LearnCard/commit/784f0c9b346a5f7e4e2c618a9b976dcaa90fafe3) Thanks [@smurflo2](https://github.com/smurflo2)! - feat: [LC-2194] Support versioned ConsentFlow updates and user review.
|
|
8
|
+
|
|
9
|
+
Keep a connection's URI and history while publishing immutable access updates. New optional read/write choices stay off; required additions pause writes until the user reviews the changes. Add explicit update acceptance, review notifications, deadlines, once-only AutoBoost delivery, and safe retirement. Unsaved request previews no longer require a URI.
|
|
10
|
+
|
|
11
|
+
Preserve existing grants in partial scope updates, gate Lambda startup on legacy snapshots, and retain once-only delivery during explicit one-time updates. Localize review and history content, recover from cancelled guardian checks and concurrent updates, and keep handled notifications safe to reopen.
|
|
12
|
+
|
|
13
|
+
Retry transient Lambda migration failures without poisoning warm application imports. Record completed migrations for fast cold starts, report malformed request IDs without credential data, and identify retained ambiguous AutoBoost claims for reconciliation. Load runtime secrets before importing the scheduled deadline worker, including secrets-only Lambda deployments. Keep inbox maintenance coverage behavioral rather than pinning Lambda wrapper source text.
|
|
14
|
+
|
|
15
|
+
Recover valid, unversioned contracts created after the migration marker through scoped version-1 initialization. Atomically backfill only their existing connections, preserve global migration completion, and keep missing history on already-versioned or malformed contracts fail-closed.
|
|
16
|
+
|
|
17
|
+
Settle guardian PIN actions on external dismissal or unmount without cancelling valid submissions. Cover reapproval, signing failures and referral cancellation with the current PIN modal contract. Clear stacked overlays before opening a contract-update review. Cancel delayed modal-removal timers when their provider unmounts while preserving closing animations. Use stable localization keys independent of English labels and stop proposing optional defaults after their window expires.
|
|
18
|
+
|
|
19
|
+
Route pending and suspended connections from ordinary consent entry to explicit update review. Recover the same way when the latest-approval error arrives during an open consent dialog, without treating the connection as approved or bypassing guardian checks.
|
|
20
|
+
|
|
21
|
+
Reject overlapping top-level and nested SDK scope patches instead of silently dropping changes. Restore strict type-only imports, declare the runnable update snippet's SDK contract, and narrow unsuccessful notification reads in end-to-end consumers without raising the typecheck allowance.
|
|
22
|
+
|
|
23
|
+
Include cumulative changes in consent records so users can approve all required additions across multiple unreviewed versions. Clear the pending optional-choice marker only when the holder successfully saves their choices.
|
|
24
|
+
|
|
25
|
+
Resolve built-in request categories and personal fields to localized labels and descriptions in English, Spanish, French, and Arabic, including learning history and career/AI categories. Recognize the legitimate French cognates “Image” and “Qualifications” in the existing untranslated-value guard.
|
|
26
|
+
|
|
27
|
+
Dismiss Alerts when opening a contract-update review without waiting for read-status writes. Give unread indicators their own layout space so they cannot overlap notification dates.
|
|
28
|
+
|
|
29
|
+
Use one shared request form with the original creation controls for creating and editing requests, without per-item purpose fields or added default-enabled checkboxes. Keep the overall update explanation separate. Replace JSON authoring with readable changes and Preview Update / Publish Update actions in the Contracts tab. Show an accessible help icon and meaningful existing-access/defaults disclosures.
|
|
30
|
+
|
|
31
|
+
Start new optional review controls from their Opt-in/Opt-out settings without silently granting access. Use the edited request's defaults in previews, refresh saved choices when reopening without overwriting active edits, and reduce the extra spacing below the current version.
|
|
32
|
+
|
|
33
|
+
Separate Advanced Options from changes, published feedback, and actions. Add space below the current version while keeping the image's remove control in its original outside corner.
|
|
34
|
+
|
|
35
|
+
Show a clear unavailable state for networks that omit contract version metadata, including cached responses. Keep publishing disabled until a versioned response is available, and never assume an unversioned response is version 1.
|
|
36
|
+
|
|
37
|
+
Use direct Mongo connections for the local Docker APIs so the single-node replica's localhost address does not prevent them from starting. Gate Mongo-dependent services on a writable primary so they do not exit during replica initialization or election.
|
|
38
|
+
|
|
39
|
+
Pre-bundle the remaining workspace crypto and cloud-client dependencies before serving the local app, avoiding dependency-discovery reloads during browser startup.
|
|
40
|
+
|
|
41
|
+
Open an on-demand Update contract modal from each configured request in the Contracts tab, rather than the Testing tab. Reveal the update explanation only after edits, separate it from grouped current/next values, and keep user-review previews in the shared modal stack for correct focus and Escape behavior.
|
|
42
|
+
|
|
43
|
+
Breaking SDK/API changes: use `updateContract` instead of the removed `addAutoBoostsToContract` and `removeAutoBoostsFromContract` SDK methods. One-time consent status is now `consumed`, not `stale`. The deprecated HTTP AutoBoost routes remain available for one compatibility release and use the versioned update path. Legacy AutoBoost additions also pause writes and synchronization pending explicit holder review; coordinate partner upgrades and support `getConsentStatus` / `reviewUrl` before rollout.
|
|
44
|
+
|
|
45
|
+
Reject stale editor drafts with their original expected version, treat equivalent updates as no-ops, require future reconsent deadlines, and restrict legacy AutoBoost publications to contract owners. Paginate tied consent-data timestamps with stable opaque cursors and preserve all unreviewed optional additions across later updates.
|
|
46
|
+
|
|
47
|
+
Track each holder's last explicit review, backfill that baseline from transaction history, and timestamp legacy snapshots at the revision actually captured. Require notification and approval when an existing item's reason changes; keep redirect-only changes quiet. Retain ambiguous initial AutoBoost claims and reject mismatched concurrent initial credential deliveries.
|
|
48
|
+
|
|
49
|
+
Show material metadata, writer, and automatic-delivery changes alongside scope updates. Refresh holder terms before enabling review edits, populate newly enabled personal fields from the holder profile, and use a structured approval-required reason instead of matching error text.
|
|
50
|
+
|
|
51
|
+
Regenerate the Python API client from the current router graph, including all consent lifecycle states, versioned updates, and review metadata. Omit `None` for ordinary non-nullable optional inputs, preserve nullable values, and retain the allocation holder's explicit-null rejection instead of silently treating it as an omission.
|
|
52
|
+
|
|
53
|
+
Preserve existing delegated AutoBoost issuers when owners publish unchanged configurations, while keeping new configurations owner-issued and rejecting changes to an existing delegated signer. Defer new cross-account setup until an explicit issuer-authorization flow is available. Use pre-upgrade persisted fixtures for legacy-delegation regressions without reopening writer publication, and fix the signer mock's recursive self-call in consent regressions.
|
|
54
|
+
|
|
55
|
+
Keep saves from already handled reviews in ordinary sharing-update history, and preserve the saved one-time setting when update or reconsent inputs omit it.
|
|
56
|
+
|
|
57
|
+
Use opaque timestamp-and-ID cursors for holder consent lists, between-profile data, transaction history, and holder exports as well as owner data pages. Preserve legacy timestamp fallbacks and reject malformed or pre-upgrade date-only cursors with `BAD_REQUEST`; restart pagination without a cursor after upgrading.
|
|
58
|
+
|
|
59
|
+
Pin owned verification review links to the allocated app origin so real consent review URLs never escape to an unrelated localhost development server.
|
|
60
|
+
|
|
61
|
+
Explain approval notifications above Publish Update without changing checked-by-default Opt-out selections. Synchronize the CLI method catalog with the versioned contract SDK, removing obsolete AutoBoost commands and exposing update, history, status, and acceptance methods.
|
|
62
|
+
|
|
63
|
+
Use neutral changed-request summaries and Updated badges for existing-scope edits, including reason-only reviews. Reserve new-access headlines and new-item counts for pure scope additions without material request-detail edits, and retain existing optional choices during approval.
|
|
64
|
+
|
|
65
|
+
### Minor Changes
|
|
66
|
+
|
|
67
|
+
- [#1904](https://github.com/learningeconomy/LearnCard/pull/1904) [`69b80366c48e0f458b3bb50f25166c90ecaa2d6d`](https://github.com/learningeconomy/LearnCard/commit/69b80366c48e0f458b3bb50f25166c90ecaa2d6d) Thanks [@gerardopar](https://github.com/gerardopar)! - Add branded campaign broadcast emails, duplicate-safe reservations, signed public unsubscribe, and private announcement email/push preferences.
|
|
68
|
+
|
|
69
|
+
- [#1839](https://github.com/learningeconomy/LearnCard/pull/1839) [`0caa0e478bce246793893e488f37ee90c9b00a1a`](https://github.com/learningeconomy/LearnCard/commit/0caa0e478bce246793893e488f37ee90c9b00a1a) Thanks [@gerardopar](https://github.com/gerardopar)! - Add campaign test-to-me and paced audience notification dispatch, ANNOUNCEMENT metadata, delivery acknowledgement bookkeeping, and retry-safe inbox deduplication.
|
|
70
|
+
|
|
71
|
+
Deploy lca-api's enum and campaign deduplication support before enabling brain-service dispatch. Push retains the existing best-effort delivery behavior.
|
|
72
|
+
|
|
73
|
+
- [#1962](https://github.com/learningeconomy/LearnCard/pull/1962) [`2c60b1a760958cbfe2525bc951d2381332e1aa48`](https://github.com/learningeconomy/LearnCard/commit/2c60b1a760958cbfe2525bc951d2381332e1aa48) Thanks [@Custard7](https://github.com/Custard7)! - Add holder-authorized pre-accept managed delivery receipts and shared binding validation.
|
|
74
|
+
Allow refresh callers to pin the original public status and refresh service, and reject
|
|
75
|
+
changed managed versions without a strictly newer signed validFrom. Verify managed
|
|
76
|
+
deliveries before claim previews, acceptance and local indexing, and retain their
|
|
77
|
+
validated binding with the local index record.
|
|
78
|
+
|
|
79
|
+
Add a strict ciphertext-only holder handoff contract, an explicit-recipient DAG JWE
|
|
80
|
+
primitive that does not add the caller, and a shared exact recipient-key-set check.
|
|
81
|
+
|
|
82
|
+
Enable server-side holder-mode (student-only encrypted) managed sends and publishes.
|
|
83
|
+
`boost.prepareRefreshableSend({ encryption: 'holder' })` returns the exact
|
|
84
|
+
key-agreement recipient set (holder + current managers) to encrypt to and pins the
|
|
85
|
+
refresh aggregate to holder mode. New issuer routes
|
|
86
|
+
`credentialRefresh.sendHolderEncryptedRefreshable`,
|
|
87
|
+
`credentialRefresh.publishHolderEncryptedRefreshable` and
|
|
88
|
+
`credentialRefresh.getEncryptionRecipients` accept and deliver an already-encrypted
|
|
89
|
+
handoff without ever decrypting it; a manager-set change since prepare fails with
|
|
90
|
+
`CONFLICT`/`RECIPIENTS_CHANGED` instead of silently narrowing who can decrypt. A
|
|
91
|
+
holder-mode aggregate rejects inbox recipients, signed-credential-only sends, mixed
|
|
92
|
+
network/holder sends on the same aggregate, and signing-authority publication.
|
|
93
|
+
|
|
94
|
+
SDK support: `send({ refresh: true, encryption: 'holder' })` builds and signs the
|
|
95
|
+
credential locally exactly as the network-mode path does, then encrypts it to the
|
|
96
|
+
prepared recipient set with `createDagJweExact`, checks the resulting JWE's recipient
|
|
97
|
+
set and the signed credential's binding before ever calling the network, and sends
|
|
98
|
+
only the ciphertext handoff via `credentialRefresh.sendHolderEncryptedRefreshable`. A
|
|
99
|
+
`RECIPIENTS_CHANGED` conflict is retried once after re-fetching
|
|
100
|
+
`credentialRefresh.getEncryptionRecipients`. The new `publishHolderEncryptedRefreshable`
|
|
101
|
+
method does the same for later versions with an explicit `notify` flag. Both reject
|
|
102
|
+
client-side for inbox recipients, a caller-supplied `signedCredential`, and wallets
|
|
103
|
+
without local signing or the Encryption plugin; an old server response missing
|
|
104
|
+
`recipientKeyIds` is rejected rather than silently sent in network mode.
|
|
105
|
+
|
|
106
|
+
Recover authenticated absent-status bindings lazily for legacy deliveries, using the
|
|
107
|
+
stored JSON string `null` to distinguish verified absence from a missing binding.
|
|
108
|
+
Allow explicit null status repair only when it matches the original status digest.
|
|
109
|
+
Legacy receipts without a stored refresh descriptor explicitly bind only the unique
|
|
110
|
+
allocated managed entry; exact receipts continue to bind the entire signed shape.
|
|
111
|
+
Holder publishing preserves a supplied original refresh descriptor in legacy mode,
|
|
112
|
+
and fails with repair/reissue guidance when that descriptor is unavailable.
|
|
113
|
+
Holder sends also preserve template-supplied external status entries instead of
|
|
114
|
+
forcing new server status allocation.
|
|
115
|
+
|
|
116
|
+
### Patch Changes
|
|
117
|
+
|
|
118
|
+
- [#1872](https://github.com/learningeconomy/LearnCard/pull/1872) [`3505f004376543ff4c723921868e17c400142884`](https://github.com/learningeconomy/LearnCard/commit/3505f004376543ff4c723921868e17c400142884) Thanks [@TaylorBeeston](https://github.com/TaylorBeeston)! - Install python3, make, and g++ during `bun install` in the shared monorepo Docker image so linux/arm64 builds can compile native addons (utf-8-validate) via node-gyp.
|
|
119
|
+
|
|
120
|
+
- [#1959](https://github.com/learningeconomy/LearnCard/pull/1959) [`bde3fe0f15a780d9fafc699096a9a0307502f529`](https://github.com/learningeconomy/LearnCard/commit/bde3fe0f15a780d9fafc699096a9a0307502f529) Thanks [@Custard7](https://github.com/Custard7)! - Use server-bound public status coordinates for managed credential sends, preserving status descriptors across credential versions. Add the managed status repair contract.
|
|
121
|
+
|
|
122
|
+
Support external HTTPS Bitstring Status Lists for managed issuance, publication and repair without reserving external indexes. Preserve template-provided status descriptors and report statusManagement separately from the signed refresh receipt. Managed lifecycle actions on external entries fail with a provider-specific precondition error rather than reporting a network-only revocation or suspension.
|
|
123
|
+
|
|
124
|
+
Gate preparation-time status binding on client capability so existing clients can continue allocating status coordinates before signing. Preserve the selected mode across idempotent retries.
|
|
125
|
+
|
|
126
|
+
- [#1960](https://github.com/learningeconomy/LearnCard/pull/1960) [`751579d9c14116dbf6d0e7f7d62f489c81c39db2`](https://github.com/learningeconomy/LearnCard/commit/751579d9c14116dbf6d0e7f7d62f489c81c39db2) Thanks [@Custard7](https://github.com/Custard7)! - Keep managed and signed-only send anchors limited to explicit public display metadata, disable request-input telemetry on credential routes, and remove signing-key debug output. Add bounded public update summaries and enumerated update reasons. Managed send request fingerprints now use a versioned server HMAC over public metadata only. The inline template's name is never copied to the anchor, but its category is copied when `display.category` is omitted, since consent-flow write authorization is keyed on a Boost's category and treats an absent one as unrestricted.
|
|
127
|
+
|
|
128
|
+
- Updated dependencies [[`e9d738eea3b477dbd82bde171d3c5f8ffa2efbc5`](https://github.com/learningeconomy/LearnCard/commit/e9d738eea3b477dbd82bde171d3c5f8ffa2efbc5), [`69b80366c48e0f458b3bb50f25166c90ecaa2d6d`](https://github.com/learningeconomy/LearnCard/commit/69b80366c48e0f458b3bb50f25166c90ecaa2d6d), [`69b80366c48e0f458b3bb50f25166c90ecaa2d6d`](https://github.com/learningeconomy/LearnCard/commit/69b80366c48e0f458b3bb50f25166c90ecaa2d6d), [`0caa0e478bce246793893e488f37ee90c9b00a1a`](https://github.com/learningeconomy/LearnCard/commit/0caa0e478bce246793893e488f37ee90c9b00a1a), [`fea9c25ec76f230944a1713500a280c80e2a9cc0`](https://github.com/learningeconomy/LearnCard/commit/fea9c25ec76f230944a1713500a280c80e2a9cc0), [`bde3fe0f15a780d9fafc699096a9a0307502f529`](https://github.com/learningeconomy/LearnCard/commit/bde3fe0f15a780d9fafc699096a9a0307502f529), [`784f0c9b346a5f7e4e2c618a9b976dcaa90fafe3`](https://github.com/learningeconomy/LearnCard/commit/784f0c9b346a5f7e4e2c618a9b976dcaa90fafe3), [`751579d9c14116dbf6d0e7f7d62f489c81c39db2`](https://github.com/learningeconomy/LearnCard/commit/751579d9c14116dbf6d0e7f7d62f489c81c39db2), [`2c60b1a760958cbfe2525bc951d2381332e1aa48`](https://github.com/learningeconomy/LearnCard/commit/2c60b1a760958cbfe2525bc951d2381332e1aa48), [`4caf6a99c7a204d7f211737190d85eeebe736eb0`](https://github.com/learningeconomy/LearnCard/commit/4caf6a99c7a204d7f211737190d85eeebe736eb0)]:
|
|
129
|
+
- @learncard/types@6.0.0
|
|
130
|
+
- @learncard/email-templates@1.3.0
|
|
131
|
+
- @learncard/helpers@1.8.0
|
|
132
|
+
- @learncard/vc-plugin@1.7.0
|
|
133
|
+
- @learncard/encryption-plugin@1.2.0
|
|
134
|
+
- @learncard/credential-library@2.1.7
|
|
135
|
+
- @learncard/core@9.4.44
|
|
136
|
+
- @learncard/did-web-plugin@1.1.44
|
|
137
|
+
- @learncard/didkey-plugin@1.1.44
|
|
138
|
+
- @learncard/didkit-plugin@1.10.10
|
|
139
|
+
- @learncard/didkit-plugin-node@0.3.10
|
|
140
|
+
- @learncard/learn-card-plugin@1.2.44
|
|
141
|
+
- @learncard/vc-templates-plugin@1.1.44
|
|
142
|
+
- @learncard/crypto-plugin@1.1.44
|
|
143
|
+
- @learncard/dynamic-loader-plugin@1.1.44
|
|
144
|
+
- @learncard/expiration-plugin@1.2.44
|
|
145
|
+
|
|
146
|
+
## 4.1.3
|
|
147
|
+
|
|
148
|
+
### Patch Changes
|
|
149
|
+
|
|
150
|
+
- Updated dependencies [[`27be1a449118c3c9b69f1fd961cf0b7fe3cbcdb6`](https://github.com/learningeconomy/LearnCard/commit/27be1a449118c3c9b69f1fd961cf0b7fe3cbcdb6)]:
|
|
151
|
+
- @learncard/types@5.24.2
|
|
152
|
+
- @learncard/credential-library@2.1.6
|
|
153
|
+
- @learncard/core@9.4.43
|
|
154
|
+
- @learncard/helpers@1.7.3
|
|
155
|
+
- @learncard/did-web-plugin@1.1.43
|
|
156
|
+
- @learncard/didkey-plugin@1.1.43
|
|
157
|
+
- @learncard/didkit-plugin@1.10.9
|
|
158
|
+
- @learncard/didkit-plugin-node@0.3.9
|
|
159
|
+
- @learncard/encryption-plugin@1.1.43
|
|
160
|
+
- @learncard/learn-card-plugin@1.2.43
|
|
161
|
+
- @learncard/vc-plugin@1.6.9
|
|
162
|
+
- @learncard/vc-templates-plugin@1.1.43
|
|
163
|
+
- @learncard/crypto-plugin@1.1.43
|
|
164
|
+
- @learncard/dynamic-loader-plugin@1.1.43
|
|
165
|
+
- @learncard/expiration-plugin@1.2.43
|
|
166
|
+
|
|
3
167
|
## 4.1.2
|
|
4
168
|
|
|
5
169
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ This service exposes the LearnCard Network API and local Neo4j-backed skills flo
|
|
|
4
4
|
|
|
5
5
|
## Live consent data for AI consumers
|
|
6
6
|
|
|
7
|
-
`getConsentedDataForDid` returns data from live grants and authorized one-time grants (`oneTime: true`, stored with `status: '
|
|
7
|
+
`getConsentedDataForDid` returns data from live grants and authorized one-time grants (`oneTime: true`, stored with `status: 'consumed'`) between the authenticated contract owner and the requested profile. Pending and suspended updates retain reads under the user's previously accepted version; they do not enable newly requested data, writes, AutoBoosts, or synchronization. Withdrawn grants and consumed grants without the one-time flag are excluded. Term, contract and category expirations are enforced; empty expiry values mean no expiry, while malformed nonempty dates never authorize access. One-time means a fixed sharing grant, not a destructive read-once API; withdrawal still revokes subsequent retrieval. Malformed legacy terms are omitted rather than authorizing data or failing every grant in the response.
|
|
8
8
|
|
|
9
9
|
- `termsUri`, `contractUri`, `status` and `terms` identify the current grant and its permissions.
|
|
10
10
|
- `createdAt` is the original grant time when known. `date` is the latest consent update time. No historical timestamp is invented.
|
|
@@ -80,5 +80,31 @@ authorities, or contracts.
|
|
|
80
80
|
|
|
81
81
|
## Notes
|
|
82
82
|
|
|
83
|
+
### Managed public status repair
|
|
84
|
+
|
|
85
|
+
An issuer can call `credentialRefresh.attachStatusEntries({ refreshId, credentialStatus })`
|
|
86
|
+
with the original signed credential's exact status descriptor. Object versus array shape,
|
|
87
|
+
array order, and all descriptor fields must match the stored HMAC. The route validates
|
|
88
|
+
local issuer-owned coordinates and reconciles an existing revocation or suspension.
|
|
89
|
+
Credentials without supported public status entries cannot be repaired this way.
|
|
90
|
+
|
|
91
|
+
New status fingerprints use `<keyVersion>:<base64url HMAC-SHA256>`. Configure
|
|
92
|
+
`CREDENTIAL_REFRESH_DIGEST_KEY_VERSION` (default `v1`) with
|
|
93
|
+
`CREDENTIAL_REFRESH_DIGEST_SECRET`. `CREDENTIAL_REFRESH_DIGEST_PREVIOUS_KEYS` is a JSON
|
|
94
|
+
object mapping retained versions to their secret keys (default `{}`). Unversioned legacy
|
|
95
|
+
fingerprints accept the current key or an explicitly retained previous key. Never log these
|
|
96
|
+
secrets. Removing a previous key disables repair for fingerprints made with that key.
|
|
97
|
+
|
|
98
|
+
Lifecycle mutations join the relationship update and status-list signing/write in one
|
|
99
|
+
Neo4j transaction. A failed bit write rolls back the relationship, including unsuspension;
|
|
100
|
+
retry the original mutation. No pending-sync worker is needed for these atomic writes.
|
|
101
|
+
|
|
102
|
+
Managed versions share one status binding. Ordinary deliveries reserve their local
|
|
103
|
+
coordinates under the same list locks and cannot reuse a managed credential's index.
|
|
104
|
+
Binding and lifecycle writes lock the root, aggregate, then sorted status lists;
|
|
105
|
+
attaching coordinates to an existing root also reconciles its lifecycle atomically.
|
|
106
|
+
Legacy deliveries without public status metadata retain network-only lifecycle state;
|
|
107
|
+
repair requires supported entries authenticated by the original status fingerprint.
|
|
108
|
+
|
|
83
109
|
- The default fixture is idempotent by framework and skill ID, so running the seed command multiple times does not duplicate data.
|
|
84
110
|
- Seeded skills are compatible with the existing skill search, boost alignment, and OBv3 alignment flows.
|
package/bootstrapLambda.test.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import type { APIGatewayProxyEventV2, Context } from 'aws-lambda';
|
|
2
2
|
import { beforeEach, expect, it, vi } from 'vitest';
|
|
3
3
|
|
|
4
|
-
const mocks = vi.hoisted(() => ({
|
|
4
|
+
const mocks = vi.hoisted(() => ({
|
|
5
|
+
bootstrap: vi.fn(),
|
|
6
|
+
getApp: vi.fn(),
|
|
7
|
+
handler: vi.fn(),
|
|
8
|
+
migrate: vi.fn(),
|
|
9
|
+
}));
|
|
5
10
|
|
|
6
11
|
vi.mock('@learncard/service-config', () => ({ bootstrapLambda: mocks.bootstrap }));
|
|
7
12
|
vi.mock('./src/config/stageConfig', () => ({ base: {}, stages: { dev: {}, production: {} } }));
|
|
13
|
+
vi.mock('./src/helpers/consentflow-legacy-migration.helpers', () => ({
|
|
14
|
+
migrateLegacyConsentFlowContracts: mocks.migrate,
|
|
15
|
+
}));
|
|
8
16
|
|
|
9
17
|
const LAMBDA_APP_HANDLERS = [
|
|
10
18
|
'trpcHandler',
|
|
@@ -17,32 +25,20 @@ const LAMBDA_APP_HANDLERS = [
|
|
|
17
25
|
'inboxQueueDispatcher',
|
|
18
26
|
'inboxDeadLetterWorker',
|
|
19
27
|
'notificationsWorker',
|
|
28
|
+
'campaignDispatchWorker',
|
|
29
|
+
'campaignUnsubscribeHandler',
|
|
20
30
|
'inboxMaintenanceHandler',
|
|
21
31
|
] as const;
|
|
22
32
|
|
|
23
|
-
vi.mock('./lambdaApp', () =>
|
|
24
|
-
Object.fromEntries(LAMBDA_APP_HANDLERS.map(name => [name, mocks.handler]))
|
|
25
|
-
);
|
|
26
|
-
|
|
27
33
|
beforeEach(() => {
|
|
28
34
|
vi.resetModules();
|
|
29
35
|
vi.clearAllMocks();
|
|
30
36
|
mocks.bootstrap.mockReturnValue(mocks.getApp);
|
|
37
|
+
mocks.getApp.mockResolvedValue(
|
|
38
|
+
Object.fromEntries(LAMBDA_APP_HANDLERS.map(name => [name, mocks.handler]))
|
|
39
|
+
);
|
|
31
40
|
mocks.handler.mockResolvedValue({ statusCode: 200 });
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
it('bootstraps the API once with checked-in stage config', async () => {
|
|
35
|
-
vi.stubEnv('AWS_LAMBDA_FUNCTION_NAME', 'lcn-brain-service-dev-trpc');
|
|
36
|
-
vi.stubEnv('LAMBDA_STAGE', 'dev');
|
|
37
|
-
await import('./lambda');
|
|
38
|
-
expect(mocks.bootstrap).toHaveBeenCalledTimes(1);
|
|
39
|
-
expect(mocks.bootstrap).toHaveBeenCalledWith({
|
|
40
|
-
base: {},
|
|
41
|
-
stages: { dev: {}, production: {} },
|
|
42
|
-
stage: 'dev',
|
|
43
|
-
importApp: expect.any(Function),
|
|
44
|
-
});
|
|
45
|
-
vi.unstubAllEnvs();
|
|
41
|
+
mocks.migrate.mockResolvedValue(undefined);
|
|
46
42
|
});
|
|
47
43
|
|
|
48
44
|
it('uses CONFIG_STAGE outside Lambda rather than LAMBDA_STAGE', async () => {
|
|
@@ -54,19 +50,61 @@ it('uses CONFIG_STAGE outside Lambda rather than LAMBDA_STAGE', async () => {
|
|
|
54
50
|
vi.unstubAllEnvs();
|
|
55
51
|
});
|
|
56
52
|
|
|
57
|
-
it('
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
it.each(LAMBDA_APP_HANDLERS)('%s waits until legacy access is migrated', async handler => {
|
|
54
|
+
let finishMigration!: () => void;
|
|
55
|
+
mocks.migrate.mockReturnValue(
|
|
56
|
+
new Promise<void>(resolve => {
|
|
57
|
+
finishMigration = resolve;
|
|
58
|
+
})
|
|
60
59
|
);
|
|
61
60
|
const lambda = await import('./lambda');
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
expect(
|
|
71
|
-
|
|
61
|
+
let finished = false;
|
|
62
|
+
const request = lambda[handler]({} as never, {} as never, vi.fn()).finally(() => {
|
|
63
|
+
finished = true;
|
|
64
|
+
});
|
|
65
|
+
await vi.waitFor(() => expect(mocks.migrate).toHaveBeenCalled());
|
|
66
|
+
expect(finished).toBe(false);
|
|
67
|
+
finishMigration();
|
|
68
|
+
await request;
|
|
69
|
+
expect(finished).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('retries a failed migration and serves concurrent and subsequent healthy requests', async () => {
|
|
73
|
+
const failure = new Error('Database unavailable');
|
|
74
|
+
let finishMigration!: () => void;
|
|
75
|
+
mocks.migrate
|
|
76
|
+
.mockRejectedValueOnce(failure)
|
|
77
|
+
.mockImplementationOnce(
|
|
78
|
+
() =>
|
|
79
|
+
new Promise<void>(resolve => {
|
|
80
|
+
finishMigration = resolve;
|
|
81
|
+
})
|
|
82
|
+
)
|
|
83
|
+
.mockResolvedValue(undefined);
|
|
84
|
+
const lambda = await import('./lambda');
|
|
85
|
+
await expect(
|
|
86
|
+
lambda.trpcHandler({} as APIGatewayProxyEventV2, {} as Context, vi.fn())
|
|
87
|
+
).rejects.toBe(failure);
|
|
88
|
+
|
|
89
|
+
let firstFinished = false;
|
|
90
|
+
let secondFinished = false;
|
|
91
|
+
const first = lambda
|
|
92
|
+
.trpcHandler({} as APIGatewayProxyEventV2, {} as Context, vi.fn())
|
|
93
|
+
.finally(() => {
|
|
94
|
+
firstFinished = true;
|
|
95
|
+
});
|
|
96
|
+
const second = lambda.openApiHandler({} as never, {} as never, vi.fn()).finally(() => {
|
|
97
|
+
secondFinished = true;
|
|
98
|
+
});
|
|
99
|
+
await vi.waitFor(() => expect(mocks.migrate).toHaveBeenCalledTimes(2));
|
|
100
|
+
expect(firstFinished).toBe(false);
|
|
101
|
+
expect(secondFinished).toBe(false);
|
|
102
|
+
finishMigration();
|
|
103
|
+
await Promise.all([first, second]);
|
|
104
|
+
expect(mocks.migrate).toHaveBeenCalledTimes(2);
|
|
105
|
+
|
|
106
|
+
await expect(
|
|
107
|
+
lambda.trpcHandler({} as APIGatewayProxyEventV2, {} as Context, vi.fn())
|
|
108
|
+
).resolves.toEqual({ statusCode: 200 });
|
|
109
|
+
expect(mocks.migrate).toHaveBeenCalledTimes(2);
|
|
72
110
|
});
|
package/config/config.dev.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"CAMPAIGN_APP_ORIGINS": "{\"learncard\":\"https://example.com\"}",
|
|
2
3
|
"CLIENT_APP_DOMAIN_NAME": "example.com",
|
|
3
4
|
"CREDENTIAL_REFRESH_ENABLED": "false",
|
|
4
5
|
"CREDENTIAL_REFRESH_NOTIFICATION_WINDOW_HOURS": "24",
|
|
@@ -13,8 +14,8 @@
|
|
|
13
14
|
"SHARE_LINK_MAINTENANCE_ALLOW_INSECURE_LOOPBACK": "false",
|
|
14
15
|
"SHARE_LINK_MAINTENANCE_AUDIENCE": "did:web:cloud.example.com",
|
|
15
16
|
"SHARE_LINK_MAINTENANCE_BUDGET_MS": "60000",
|
|
16
|
-
"SHARE_LINK_MAINTENANCE_CLAIM_MS": "300000",
|
|
17
17
|
"SHARE_LINK_MAINTENANCE_CLAIMANT": "brain-share-link-maintenance",
|
|
18
|
+
"SHARE_LINK_MAINTENANCE_CLAIM_MS": "300000",
|
|
18
19
|
"SHARE_LINK_MAINTENANCE_CLEANUP_LIMIT": "25",
|
|
19
20
|
"SHARE_LINK_MAINTENANCE_FINALIZE_RESERVE_MS": "5000",
|
|
20
21
|
"SHARE_LINK_MAINTENANCE_GRAPH_TIMEOUT_MS": "15000",
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { Context } from 'aws-lambda';
|
|
2
|
+
import { afterEach, beforeEach, expect, it, vi } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import baseConfig from './config/config.json';
|
|
5
|
+
import devConfig from './config/config.dev.json';
|
|
6
|
+
|
|
7
|
+
const { send, deadlineAppImport, databaseRun, loadedEnvironment } = vi.hoisted(() => ({
|
|
8
|
+
send: vi.fn(),
|
|
9
|
+
deadlineAppImport: vi.fn(),
|
|
10
|
+
databaseRun: vi.fn(),
|
|
11
|
+
loadedEnvironment: vi.fn(),
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
vi.mock('@aws-sdk/client-secrets-manager', () => ({
|
|
15
|
+
SecretsManagerClient: class {
|
|
16
|
+
send = send;
|
|
17
|
+
destroy = vi.fn();
|
|
18
|
+
},
|
|
19
|
+
GetSecretValueCommand: class {
|
|
20
|
+
constructor(public input: { SecretId: string }) {}
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
// Static imports would validate configuration before the cold-start secrets boundary.
|
|
24
|
+
vi.mock('./consentFlowDeadlineLambdaApp', async importOriginal => {
|
|
25
|
+
deadlineAppImport();
|
|
26
|
+
return importOriginal();
|
|
27
|
+
});
|
|
28
|
+
vi.mock('./src/instance', async () => {
|
|
29
|
+
// Keep real import-time validation; replace only the database transport.
|
|
30
|
+
const { environment } = await import('./src/config/environment');
|
|
31
|
+
loadedEnvironment(environment);
|
|
32
|
+
return { neogma: { queryRunner: { run: databaseRun } } };
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
vi.resetModules();
|
|
37
|
+
send.mockReset();
|
|
38
|
+
deadlineAppImport.mockReset();
|
|
39
|
+
databaseRun.mockReset();
|
|
40
|
+
loadedEnvironment.mockReset();
|
|
41
|
+
for (const key of new Set([...Object.keys(baseConfig), ...Object.keys(devConfig)])) {
|
|
42
|
+
vi.stubEnv(key, undefined);
|
|
43
|
+
}
|
|
44
|
+
vi.stubEnv('DOTENV_CONFIG_PATH', '/dev/null');
|
|
45
|
+
vi.stubEnv('NODE_ENV', 'production');
|
|
46
|
+
vi.stubEnv('CONFIG_TENANT', '');
|
|
47
|
+
vi.stubEnv('AWS_LAMBDA_FUNCTION_NAME', 'lcn-brain-service-dev-consentFlowDeadline');
|
|
48
|
+
vi.stubEnv('LAMBDA_STAGE', 'dev');
|
|
49
|
+
vi.stubEnv('RUNTIME_SECRETS_ID', 'brain-service/dev/runtime-secrets');
|
|
50
|
+
});
|
|
51
|
+
afterEach(() => {
|
|
52
|
+
vi.unstubAllEnvs();
|
|
53
|
+
vi.useRealTimers();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('does not import or run deadline work when runtime secrets fail to load', async () => {
|
|
57
|
+
send.mockRejectedValue(new Error('secrets unavailable'));
|
|
58
|
+
const { consentFlowDeadlineHandler } = await import('./consentFlowDeadlineLambda');
|
|
59
|
+
|
|
60
|
+
await expect(
|
|
61
|
+
consentFlowDeadlineHandler({}, { getRemainingTimeInMillis: () => 30_000 } as Context)
|
|
62
|
+
).rejects.toThrow('Unable to load runtime secrets bundle');
|
|
63
|
+
expect(deadlineAppImport).not.toHaveBeenCalled();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('boots from the secrets bundle and keeps warm deadline work independent of secrets availability', async () => {
|
|
67
|
+
const secrets = {
|
|
68
|
+
SEED: 'a'.repeat(64),
|
|
69
|
+
NEO4J_URI: 'bolt://deadline-test:7687',
|
|
70
|
+
NEO4J_USERNAME: 'deadline-test',
|
|
71
|
+
NEO4J_PASSWORD: 'test-password',
|
|
72
|
+
CREDENTIAL_REFRESH_DIGEST_SECRET: 'deadline-test-refresh-digest',
|
|
73
|
+
};
|
|
74
|
+
for (const key of Object.keys(secrets)) vi.stubEnv(key, undefined);
|
|
75
|
+
send.mockImplementationOnce(async () => {
|
|
76
|
+
for (const key of Object.keys(secrets)) expect(process.env[key]).toBeUndefined();
|
|
77
|
+
expect(deadlineAppImport).not.toHaveBeenCalled();
|
|
78
|
+
return { SecretString: JSON.stringify(secrets) };
|
|
79
|
+
});
|
|
80
|
+
send.mockRejectedValue(new Error('Secrets Manager unavailable after cold start'));
|
|
81
|
+
databaseRun.mockResolvedValue({
|
|
82
|
+
records: [{ get: () => ({ toNumber: () => 2 }) }],
|
|
83
|
+
});
|
|
84
|
+
vi.useFakeTimers({ toFake: ['Date'] });
|
|
85
|
+
vi.setSystemTime(new Date('2026-01-02T00:00:00.000Z'));
|
|
86
|
+
|
|
87
|
+
const { consentFlowDeadlineHandler } = await import('./consentFlowDeadlineLambda');
|
|
88
|
+
expect(deadlineAppImport).not.toHaveBeenCalled();
|
|
89
|
+
|
|
90
|
+
// The forwarded context must prevent database writes after a slow cold start.
|
|
91
|
+
await expect(
|
|
92
|
+
consentFlowDeadlineHandler({}, { getRemainingTimeInMillis: () => 1_000 } as Context)
|
|
93
|
+
).resolves.toEqual({ suspended: 0 });
|
|
94
|
+
expect(databaseRun).not.toHaveBeenCalled();
|
|
95
|
+
expect(loadedEnvironment).toHaveBeenCalledExactlyOnceWith(expect.objectContaining(secrets));
|
|
96
|
+
|
|
97
|
+
// Scheduled input cannot replace the server's cutoff, and a warm call needs no new fetch.
|
|
98
|
+
await expect(
|
|
99
|
+
consentFlowDeadlineHandler({ now: '2099-01-01T00:00:00.000Z' }, {
|
|
100
|
+
getRemainingTimeInMillis: () => 30_000,
|
|
101
|
+
} as Context)
|
|
102
|
+
).resolves.toEqual({ suspended: 2 });
|
|
103
|
+
expect(databaseRun).toHaveBeenCalledExactlyOnceWith(expect.any(String), {
|
|
104
|
+
now: '2026-01-02T00:00:00.000Z',
|
|
105
|
+
});
|
|
106
|
+
expect(send).toHaveBeenCalledOnce();
|
|
107
|
+
expect(deadlineAppImport).toHaveBeenCalledOnce();
|
|
108
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { bootstrapLambda } from '@learncard/service-config';
|
|
2
|
+
import type { consentFlowDeadlineHandler as DeadlineHandler } from './consentFlowDeadlineLambdaApp';
|
|
3
|
+
|
|
4
|
+
import { base, stages } from './src/config/stageConfig';
|
|
5
|
+
|
|
6
|
+
type ConsentFlowDeadlineApp = { consentFlowDeadlineHandler: typeof DeadlineHandler };
|
|
7
|
+
|
|
8
|
+
const getApplication = bootstrapLambda<ConsentFlowDeadlineApp>({
|
|
9
|
+
base,
|
|
10
|
+
stages,
|
|
11
|
+
stage: process.env.AWS_LAMBDA_FUNCTION_NAME
|
|
12
|
+
? process.env.LAMBDA_STAGE
|
|
13
|
+
: process.env.CONFIG_STAGE,
|
|
14
|
+
importApp: () => import('./consentFlowDeadlineLambdaApp'),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const consentFlowDeadlineHandler: typeof DeadlineHandler = (...args) =>
|
|
18
|
+
getApplication().then(app => app.consentFlowDeadlineHandler(...args));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Context } from 'aws-lambda';
|
|
2
|
+
import {
|
|
3
|
+
suspendExpiredConsentFlowTerms,
|
|
4
|
+
type ConsentFlowDeadlineSummary,
|
|
5
|
+
} from './src/helpers/consentflow-deadline.helpers';
|
|
6
|
+
|
|
7
|
+
/** Apply expired consent review deadlines; scheduled input cannot alter the cutoff. */
|
|
8
|
+
export const consentFlowDeadlineHandler = async (
|
|
9
|
+
_event: unknown,
|
|
10
|
+
context?: Pick<Context, 'getRemainingTimeInMillis'>
|
|
11
|
+
): Promise<ConsentFlowDeadlineSummary> => {
|
|
12
|
+
if ((context?.getRemainingTimeInMillis() ?? 10_000) < 2_000) return { suspended: 0 };
|
|
13
|
+
return suspendExpiredConsentFlowTerms();
|
|
14
|
+
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import { UnsignedVC, VC } from '@learncard/types';
|
|
1
|
+
import { UnsignedVC, VC, type CredentialDisplay } from '@learncard/types';
|
|
2
2
|
import { BoostInstance } from '../.././models/index';
|
|
3
3
|
import { BoostType } from '../../types/boost';
|
|
4
4
|
import { ProfileType } from '../../types/profile';
|
|
5
5
|
import { AppStoreListingType } from '../../types/app-store-listing';
|
|
6
|
-
export declare const createBoost: (credential: UnsignedVC | VC, creator: ProfileType, metadata: Omit<BoostType, "id" | "boost"> | undefined, domain: string) => Promise<BoostInstance>;
|
|
6
|
+
export declare const createBoost: (credential: UnsignedVC | VC | null, creator: ProfileType, metadata: Omit<BoostType, "id" | "boost"> | undefined, domain: string, publicDisplay?: CredentialDisplay) => Promise<BoostInstance>;
|
|
7
|
+
export declare const normalizePublicDisplay: (display: CredentialDisplay | undefined, template?: {
|
|
8
|
+
category?: string | null;
|
|
9
|
+
}) => CredentialDisplay;
|
|
10
|
+
export declare const createDisplayOnlyBoost: (display: CredentialDisplay | undefined, creator: ProfileType, domain: string, template?: {
|
|
11
|
+
category?: string | null;
|
|
12
|
+
}) => Promise<BoostInstance>;
|
|
7
13
|
export declare const createBoostForListing: (credential: UnsignedVC | VC, listing: AppStoreListingType, metadata: Omit<BoostType, "id" | "boost"> | undefined, domain: string) => Promise<BoostInstance>;
|
|
8
14
|
//# sourceMappingURL=create.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/boost/create.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/boost/create.ts"],"names":[],"mappings":"AACA,OAAO,EACH,UAAU,EACV,EAAE,EAEF,KAAK,iBAAiB,EACzB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAS,aAAa,EAA4B,MAAM,SAAS,CAAC;AACzE,OAAO,EAAe,SAAS,EAAE,MAAM,aAAa,CAAC;AAMrD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,eAAO,MAAM,WAAW,GACpB,YAAY,UAAU,GAAG,EAAE,GAAG,IAAI,EAClC,SAAS,WAAW,EACpB,UAAU,IAAI,CAAC,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,YAAK,EAC9C,QAAQ,MAAM,EACd,gBAAgB,iBAAiB,KAClC,OAAO,CAAC,aAAa,CAuDvB,CAAC;AAWF,eAAO,MAAM,sBAAsB,GAC/B,SAAS,iBAAiB,GAAG,SAAS,EACtC,WAAW;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,KACxC,iBAMF,CAAC;AAIF,eAAO,MAAM,sBAAsB,GAC/B,SAAS,iBAAiB,GAAG,SAAS,EACtC,SAAS,WAAW,EACpB,QAAQ,MAAM,EACd,WAAW;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,KACxC,OAAO,CAAC,aAAa,CASvB,CAAC;AAMF,eAAO,MAAM,qBAAqB,GAC9B,YAAY,UAAU,GAAG,EAAE,EAC3B,SAAS,mBAAmB,EAC5B,UAAU,IAAI,CAAC,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,YAAK,EAC9C,QAAQ,MAAM,KACf,OAAO,CAAC,aAAa,CA2CvB,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type CampaignAudienceSource, type PaginatedCampaignAudience } from '@learncard/types';
|
|
1
|
+
import { type CampaignAudienceSource, type CampaignAudienceResult, type PaginatedCampaignAudience } from '@learncard/types';
|
|
2
2
|
import type { CampaignAudienceQuery } from '../../types/campaign';
|
|
3
3
|
export declare const buildCampaignAudienceQuery: (rawSource: CampaignAudienceSource, domain: string) => CampaignAudienceQuery;
|
|
4
|
-
export declare const previewCampaignAudience: (campaignId: string, source: CampaignAudienceSource, domain: string) => Promise<
|
|
5
|
-
export declare const addCampaignAudience: (campaignId: string, source: CampaignAudienceSource, domain: string) => Promise<
|
|
6
|
-
export declare const pageCampaignAudience: (campaignId: string, cursor?: string, limit?: number) => Promise<PaginatedCampaignAudience>;
|
|
4
|
+
export declare const previewCampaignAudience: (campaignId: string, source: CampaignAudienceSource, domain: string) => Promise<CampaignAudienceResult>;
|
|
5
|
+
export declare const addCampaignAudience: (campaignId: string, source: CampaignAudienceSource, domain: string) => Promise<CampaignAudienceResult>;
|
|
6
|
+
export declare const pageCampaignAudience: (campaignId: string, cursor?: string, limit?: number, deliveryChannel?: "email") => Promise<PaginatedCampaignAudience>;
|
|
7
7
|
//# sourceMappingURL=audience.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audience.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/campaign/audience.ts"],"names":[],"mappings":"AAEA,OAAO,EAEH,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EACjC,MAAM,kBAAkB,CAAC;AAM1B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"audience.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/campaign/audience.ts"],"names":[],"mappings":"AAEA,OAAO,EAEH,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EACjC,MAAM,kBAAkB,CAAC;AAM1B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAiB5D,eAAO,MAAM,0BAA0B,GACnC,WAAW,sBAAsB,EACjC,QAAQ,MAAM,KACf,qBA4DF,CAAC;AAmBF,eAAO,MAAM,uBAAuB,GAChC,YAAY,MAAM,EAClB,QAAQ,sBAAsB,EAC9B,QAAQ,MAAM,KACf,OAAO,CAAC,sBAAsB,CAehC,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC5B,YAAY,MAAM,EAClB,QAAQ,sBAAsB,EAC9B,QAAQ,MAAM,KACf,OAAO,CAAC,sBAAsB,CAqBhC,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC7B,YAAY,MAAM,EAClB,SAAS,MAAM,EACf,cAAW,EACX,kBAAkB,OAAO,KAC1B,OAAO,CAAC,yBAAyB,CAkBnC,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type Campaign, type CreateCampaignInput } from '@learncard/types';
|
|
2
|
-
export declare const createCampaign: (input: CreateCampaignInput, createdByProfileId: string) => Promise<Campaign>;
|
|
2
|
+
export declare const createCampaign: (input: CreateCampaignInput, createdByProfileId: string, tenantId?: string) => Promise<Campaign>;
|
|
3
3
|
//# sourceMappingURL=create.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/campaign/create.ts"],"names":[],"mappings":"AACA,OAAO,EAGH,KAAK,QAAQ,EACb,KAAK,mBAAmB,EAC3B,MAAM,kBAAkB,CAAC;AAO1B,eAAO,MAAM,cAAc,GACvB,OAAO,mBAAmB,EAC1B,oBAAoB,MAAM,
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/accesslayer/campaign/create.ts"],"names":[],"mappings":"AACA,OAAO,EAGH,KAAK,QAAQ,EACb,KAAK,mBAAmB,EAC3B,MAAM,kBAAkB,CAAC;AAO1B,eAAO,MAAM,cAAc,GACvB,OAAO,mBAAmB,EAC1B,oBAAoB,MAAM,EAC1B,WAAW,MAAM,KAClB,OAAO,CAAC,QAAQ,CA+BlB,CAAC"}
|