@learncard/network-brain-service 3.18.0 → 3.19.1
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 +38 -2
- package/CHANGELOG.md +118 -0
- package/README.md +42 -0
- package/compose.inbox.yml +7 -0
- package/dist/accesslayer/auth-grant/read.d.ts +1 -0
- package/dist/accesslayer/auth-grant/read.d.ts.map +1 -1
- package/dist/accesslayer/consentflowcontract/relationships/create.d.ts.map +1 -1
- package/dist/accesslayer/consentflowcontract/relationships/update.d.ts.map +1 -1
- package/dist/accesslayer/credential-activity/create.d.ts.map +1 -1
- package/dist/accesslayer/credential-refresh/email-delivery.d.ts +18 -0
- package/dist/accesslayer/credential-refresh/email-delivery.d.ts.map +1 -0
- package/dist/accesslayer/credential-refresh/index.d.ts +1 -0
- package/dist/accesslayer/credential-refresh/index.d.ts.map +1 -1
- 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-batch/store.d.ts +33 -0
- package/dist/accesslayer/inbox-batch/store.d.ts.map +1 -0
- package/dist/accesslayer/inbox-credential/create.d.ts +5 -0
- package/dist/accesslayer/inbox-credential/create.d.ts.map +1 -1
- package/dist/accesslayer/inbox-credential/refresh.d.ts +71 -0
- package/dist/accesslayer/inbox-credential/refresh.d.ts.map +1 -0
- package/dist/accesslayer/inbox-credential/update.d.ts +1 -1
- package/dist/accesslayer/inbox-credential/update.d.ts.map +1 -1
- package/dist/accesslayer/presentation/read.d.ts.map +1 -1
- package/dist/accesslayer/presentation/relationships/create.d.ts +2 -2
- package/dist/accesslayer/presentation/relationships/create.d.ts.map +1 -1
- package/dist/accesslayer/presentation/relationships/read.d.ts.map +1 -1
- package/dist/accesslayer/share-link/abandon.d.ts +3 -0
- package/dist/accesslayer/share-link/abandon.d.ts.map +1 -0
- package/dist/accesslayer/share-link/cleanup.d.ts +6 -0
- package/dist/accesslayer/share-link/cleanup.d.ts.map +1 -0
- package/dist/accesslayer/share-link/errors.d.ts +8 -0
- package/dist/accesslayer/share-link/errors.d.ts.map +1 -0
- package/dist/accesslayer/share-link/finalize.d.ts +3 -0
- package/dist/accesslayer/share-link/finalize.d.ts.map +1 -0
- package/dist/accesslayer/share-link/helpers.d.ts +56 -0
- package/dist/accesslayer/share-link/helpers.d.ts.map +1 -0
- package/dist/accesslayer/share-link/index.d.ts +12 -0
- package/dist/accesslayer/share-link/index.d.ts.map +1 -0
- package/dist/accesslayer/share-link/list.d.ts +5 -0
- package/dist/accesslayer/share-link/list.d.ts.map +1 -0
- package/dist/accesslayer/share-link/read.d.ts +5 -0
- package/dist/accesslayer/share-link/read.d.ts.map +1 -0
- package/dist/accesslayer/share-link/receipt.d.ts +11 -0
- package/dist/accesslayer/share-link/receipt.d.ts.map +1 -0
- package/dist/accesslayer/share-link/recovery.d.ts +6 -0
- package/dist/accesslayer/share-link/recovery.d.ts.map +1 -0
- package/dist/accesslayer/share-link/reserve.d.ts +4 -0
- package/dist/accesslayer/share-link/reserve.d.ts.map +1 -0
- package/dist/accesslayer/share-link/revoke.d.ts +3 -0
- package/dist/accesslayer/share-link/revoke.d.ts.map +1 -0
- package/dist/accesslayer/share-link/transaction-execution.d.ts +18 -0
- package/dist/accesslayer/share-link/transaction-execution.d.ts.map +1 -0
- package/dist/accesslayer/share-link/transaction.d.ts +15 -0
- package/dist/accesslayer/share-link/transaction.d.ts.map +1 -0
- package/dist/accesslayer/share-link/types.d.ts +370 -0
- package/dist/accesslayer/share-link/types.d.ts.map +1 -0
- package/dist/app.d.ts +4 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/cache/atomic-counter.test-helpers.d.ts +3 -0
- package/dist/cache/atomic-counter.test-helpers.d.ts.map +1 -0
- package/dist/cache/atomic-counter.test.d.ts +2 -0
- package/dist/cache/atomic-counter.test.d.ts.map +1 -0
- package/dist/cache/index.d.ts +1 -1
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/config/environment.d.ts +55 -0
- package/dist/config/environment.d.ts.map +1 -1
- package/dist/constants/auth-grant.d.ts +2 -0
- package/dist/constants/auth-grant.d.ts.map +1 -1
- package/dist/credential-refresh.d.ts.map +1 -1
- package/dist/helpers/activity.helpers.d.ts +4 -0
- package/dist/helpers/activity.helpers.d.ts.map +1 -1
- package/dist/helpers/boost.helpers.d.ts.map +1 -1
- package/dist/helpers/contact-method.helpers.d.ts.map +1 -1
- package/dist/helpers/contact-method.helpers.test.d.ts +2 -0
- package/dist/helpers/contact-method.helpers.test.d.ts.map +1 -0
- package/dist/helpers/credential-refresh-email-content.helpers.d.ts +44 -0
- package/dist/helpers/credential-refresh-email-content.helpers.d.ts.map +1 -0
- package/dist/helpers/credential-refresh-email-content.helpers.test.d.ts +2 -0
- package/dist/helpers/credential-refresh-email-content.helpers.test.d.ts.map +1 -0
- package/dist/helpers/credential-refresh-email.helpers.d.ts +17 -0
- package/dist/helpers/credential-refresh-email.helpers.d.ts.map +1 -0
- package/dist/helpers/credential-refresh-proof.helpers.d.ts +4 -0
- package/dist/helpers/credential-refresh-proof.helpers.d.ts.map +1 -0
- package/dist/helpers/credential-refresh-proof.helpers.test.d.ts +2 -0
- package/dist/helpers/credential-refresh-proof.helpers.test.d.ts.map +1 -0
- package/dist/helpers/credential-refresh.helpers.d.ts +45 -2
- package/dist/helpers/credential-refresh.helpers.d.ts.map +1 -1
- package/dist/helpers/credential.helpers.d.ts +2 -1
- package/dist/helpers/credential.helpers.d.ts.map +1 -1
- package/dist/helpers/credentialSubject.helpers.d.ts +3 -0
- package/dist/helpers/credentialSubject.helpers.d.ts.map +1 -0
- package/dist/helpers/credentialSubject.helpers.test.d.ts +2 -0
- package/dist/helpers/credentialSubject.helpers.test.d.ts.map +1 -0
- package/dist/helpers/finalize-inbox.helpers.d.ts.map +1 -1
- package/dist/helpers/inbox-batch-http.helpers.d.ts +15 -0
- package/dist/helpers/inbox-batch-http.helpers.d.ts.map +1 -0
- package/dist/helpers/inbox-batch-http.helpers.test.d.ts +2 -0
- package/dist/helpers/inbox-batch-http.helpers.test.d.ts.map +1 -0
- package/dist/helpers/inbox-batch-status.helpers.d.ts +3 -0
- package/dist/helpers/inbox-batch-status.helpers.d.ts.map +1 -0
- package/dist/helpers/inbox-batch.helpers.d.ts +10 -0
- package/dist/helpers/inbox-batch.helpers.d.ts.map +1 -0
- package/dist/helpers/inbox-batch.helpers.test.d.ts +2 -0
- package/dist/helpers/inbox-batch.helpers.test.d.ts.map +1 -0
- package/dist/helpers/inbox-issuance-error.helpers.d.ts +13 -0
- package/dist/helpers/inbox-issuance-error.helpers.d.ts.map +1 -0
- package/dist/helpers/inbox-queue.helpers.d.ts +11 -0
- package/dist/helpers/inbox-queue.helpers.d.ts.map +1 -0
- package/dist/helpers/inbox-queue.helpers.test.d.ts +2 -0
- package/dist/helpers/inbox-queue.helpers.test.d.ts.map +1 -0
- package/dist/helpers/inbox-refresh.helpers.d.ts +186 -0
- package/dist/helpers/inbox-refresh.helpers.d.ts.map +1 -0
- package/dist/helpers/inbox.helpers.d.ts +9 -1
- package/dist/helpers/inbox.helpers.d.ts.map +1 -1
- package/dist/helpers/notificationMessages.d.ts +1 -1
- package/dist/helpers/notificationMessages.d.ts.map +1 -1
- package/dist/helpers/notifications.helpers.d.ts.map +1 -1
- package/dist/helpers/presentation-metadata.d.ts +4 -0
- package/dist/helpers/presentation-metadata.d.ts.map +1 -0
- package/dist/helpers/presentation.helpers.d.ts +1 -1
- package/dist/helpers/presentation.helpers.d.ts.map +1 -1
- package/dist/helpers/profile.helpers.d.ts +1 -0
- package/dist/helpers/profile.helpers.d.ts.map +1 -1
- package/dist/helpers/rateLimit.helpers.d.ts.map +1 -1
- package/dist/helpers/refresh-send-intent.helpers.d.ts +51 -0
- package/dist/helpers/refresh-send-intent.helpers.d.ts.map +1 -0
- package/dist/helpers/share-content-client/adapters.d.ts +10 -0
- package/dist/helpers/share-content-client/adapters.d.ts.map +1 -0
- package/dist/helpers/share-content-client/canonical.d.ts +7 -0
- package/dist/helpers/share-content-client/canonical.d.ts.map +1 -0
- package/dist/helpers/share-content-client/client.d.ts +5 -0
- package/dist/helpers/share-content-client/client.d.ts.map +1 -0
- package/dist/helpers/share-content-client/config.d.ts +11 -0
- package/dist/helpers/share-content-client/config.d.ts.map +1 -0
- package/dist/helpers/share-content-client/index.d.ts +6 -0
- package/dist/helpers/share-content-client/index.d.ts.map +1 -0
- package/dist/helpers/share-content-client/responses.d.ts +16 -0
- package/dist/helpers/share-content-client/responses.d.ts.map +1 -0
- package/dist/helpers/share-content-client/types.d.ts +145 -0
- package/dist/helpers/share-content-client/types.d.ts.map +1 -0
- package/dist/helpers/share-link-coordinator/budget-helpers.d.ts +5 -0
- package/dist/helpers/share-link-coordinator/budget-helpers.d.ts.map +1 -0
- package/dist/helpers/share-link-coordinator/cleanup-runner.d.ts +3 -0
- package/dist/helpers/share-link-coordinator/cleanup-runner.d.ts.map +1 -0
- package/dist/helpers/share-link-coordinator/coordinator.d.ts +4 -0
- package/dist/helpers/share-link-coordinator/coordinator.d.ts.map +1 -0
- package/dist/helpers/share-link-coordinator/index.d.ts +5 -0
- package/dist/helpers/share-link-coordinator/index.d.ts.map +1 -0
- package/dist/helpers/share-link-coordinator/recovery-runner.d.ts +9 -0
- package/dist/helpers/share-link-coordinator/recovery-runner.d.ts.map +1 -0
- package/dist/helpers/share-link-coordinator/runtime.d.ts +11 -0
- package/dist/helpers/share-link-coordinator/runtime.d.ts.map +1 -0
- package/dist/helpers/share-link-coordinator/stat.d.ts +4 -0
- package/dist/helpers/share-link-coordinator/stat.d.ts.map +1 -0
- package/dist/helpers/share-link-coordinator/types.d.ts +160 -0
- package/dist/helpers/share-link-coordinator/types.d.ts.map +1 -0
- package/dist/helpers/share-link-lifecycle/index.d.ts +5 -0
- package/dist/helpers/share-link-lifecycle/index.d.ts.map +1 -0
- package/dist/helpers/share-link-lifecycle/lease.helpers.d.ts +4 -0
- package/dist/helpers/share-link-lifecycle/lease.helpers.d.ts.map +1 -0
- package/dist/helpers/share-link-lifecycle/recovery.helpers.d.ts +21 -0
- package/dist/helpers/share-link-lifecycle/recovery.helpers.d.ts.map +1 -0
- package/dist/helpers/share-link-lifecycle/request-hash.helpers.d.ts +9 -0
- package/dist/helpers/share-link-lifecycle/request-hash.helpers.d.ts.map +1 -0
- package/dist/helpers/share-link-lifecycle/types.d.ts +14 -0
- package/dist/helpers/share-link-lifecycle/types.d.ts.map +1 -0
- package/dist/helpers/share-link-maintenance/budget.d.ts +12 -0
- package/dist/helpers/share-link-maintenance/budget.d.ts.map +1 -0
- package/dist/helpers/share-link-maintenance/config.d.ts +48 -0
- package/dist/helpers/share-link-maintenance/config.d.ts.map +1 -0
- package/dist/helpers/share-link-maintenance/index.d.ts +8 -0
- package/dist/helpers/share-link-maintenance/index.d.ts.map +1 -0
- package/dist/helpers/share-link-maintenance/runner.d.ts +19 -0
- package/dist/helpers/share-link-maintenance/runner.d.ts.map +1 -0
- package/dist/helpers/share-link-maintenance/runtime.d.ts +36 -0
- package/dist/helpers/share-link-maintenance/runtime.d.ts.map +1 -0
- package/dist/helpers/share-link-maintenance/scheduler.d.ts +18 -0
- package/dist/helpers/share-link-maintenance/scheduler.d.ts.map +1 -0
- package/dist/helpers/share-link-maintenance/telemetry.d.ts +5 -0
- package/dist/helpers/share-link-maintenance/telemetry.d.ts.map +1 -0
- package/dist/helpers/share-link-maintenance/types.d.ts +53 -0
- package/dist/helpers/share-link-maintenance/types.d.ts.map +1 -0
- package/dist/helpers/share-link-owner/config.d.ts +16 -0
- package/dist/helpers/share-link-owner/config.d.ts.map +1 -0
- package/dist/helpers/share-link-owner/diagnostics.d.ts +26 -0
- package/dist/helpers/share-link-owner/diagnostics.d.ts.map +1 -0
- package/dist/helpers/share-link-owner/lazy-initializer.d.ts +2 -0
- package/dist/helpers/share-link-owner/lazy-initializer.d.ts.map +1 -0
- package/dist/helpers/share-link-owner-projection.d.ts +4 -0
- package/dist/helpers/share-link-owner-projection.d.ts.map +1 -0
- package/dist/helpers/share-link-passcode-abuse.d.ts +2 -0
- package/dist/helpers/share-link-passcode-abuse.d.ts.map +1 -0
- package/dist/helpers/share-link-passcode.d.ts +6 -0
- package/dist/helpers/share-link-passcode.d.ts.map +1 -0
- package/dist/helpers/share-link-policy/index.d.ts +4 -0
- package/dist/helpers/share-link-policy/index.d.ts.map +1 -0
- package/dist/helpers/share-link-policy/production.d.ts +13 -0
- package/dist/helpers/share-link-policy/production.d.ts.map +1 -0
- package/dist/helpers/share-link-policy/resolver.d.ts +6 -0
- package/dist/helpers/share-link-policy/resolver.d.ts.map +1 -0
- package/dist/helpers/share-link-policy/types.d.ts +16 -0
- package/dist/helpers/share-link-policy/types.d.ts.map +1 -0
- package/dist/helpers/share-link-public/config.d.ts +13 -0
- package/dist/helpers/share-link-public/config.d.ts.map +1 -0
- package/dist/helpers/share-link-view-notification.d.ts +2 -0
- package/dist/helpers/share-link-view-notification.d.ts.map +1 -0
- package/dist/helpers/shim.d.ts +1 -1
- package/dist/helpers/shim.d.ts.map +1 -1
- package/dist/inbox-queue-local.d.ts +2 -0
- package/dist/inbox-queue-local.d.ts.map +1 -0
- package/dist/index.js +2 -2
- package/dist/models/AuthGrant.d.ts.map +1 -1
- package/dist/models/CredentialActivity.d.ts +1 -0
- package/dist/models/CredentialActivity.d.ts.map +1 -1
- package/dist/models/CredentialRefresh.d.ts +5 -2
- package/dist/models/CredentialRefresh.d.ts.map +1 -1
- package/dist/models/InboxCredential.d.ts +1 -0
- package/dist/models/InboxCredential.d.ts.map +1 -1
- package/dist/models/Presentation.d.ts +2 -0
- package/dist/models/Presentation.d.ts.map +1 -1
- package/dist/models/Profile.d.ts +2 -0
- package/dist/models/Profile.d.ts.map +1 -1
- package/dist/models/ShareLink.d.ts +44 -0
- package/dist/models/ShareLink.d.ts.map +1 -0
- package/dist/models/ShareViewReceipt.d.ts +22 -0
- package/dist/models/ShareViewReceipt.d.ts.map +1 -0
- package/dist/models/credential-refresh-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/models/share-link-constraints.d.ts +3 -0
- package/dist/models/share-link-constraints.d.ts.map +1 -0
- package/dist/openapi.d.ts.map +1 -1
- package/dist/public-share-link-http.d.ts +4 -0
- package/dist/public-share-link-http.d.ts.map +1 -0
- package/dist/routes/act-as.test.d.ts +2 -0
- package/dist/routes/act-as.test.d.ts.map +1 -0
- package/dist/routes/activity.d.ts +3 -0
- package/dist/routes/activity.d.ts.map +1 -1
- package/dist/routes/app-store.d.ts.map +1 -1
- package/dist/routes/auth-grants.d.ts +10 -0
- package/dist/routes/auth-grants.d.ts.map +1 -1
- package/dist/routes/boosts.d.ts +494 -0
- package/dist/routes/boosts.d.ts.map +1 -1
- package/dist/routes/contracts.d.ts +2 -2
- package/dist/routes/contracts.d.ts.map +1 -1
- package/dist/routes/credential-refreshes.d.ts.map +1 -1
- package/dist/routes/credentials.d.ts +1 -1
- package/dist/routes/credentials.d.ts.map +1 -1
- package/dist/routes/inbox.d.ts +953 -11
- package/dist/routes/inbox.d.ts.map +1 -1
- package/dist/routes/index.d.ts +154 -85
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/presentations.d.ts +1 -0
- package/dist/routes/presentations.d.ts.map +1 -1
- package/dist/routes/profile-manager.d.ts.map +1 -1
- package/dist/routes/profiles.d.ts.map +1 -1
- package/dist/routes/public-share-links.d.ts +230 -0
- package/dist/routes/public-share-links.d.ts.map +1 -0
- package/dist/routes/share-links.d.ts +844 -0
- package/dist/routes/share-links.d.ts.map +1 -0
- package/dist/routes/workflows.d.ts.map +1 -1
- package/dist/services/delivery/adapters/postmark.adapter.d.ts.map +1 -1
- package/dist/services/delivery/adapters/postmark.adapter.test.d.ts +2 -0
- package/dist/services/delivery/adapters/postmark.adapter.test.d.ts.map +1 -0
- package/dist/services/registry/registry.factory.d.ts.map +1 -1
- package/dist/types/activity.d.ts +4 -0
- package/dist/types/activity.d.ts.map +1 -1
- package/dist/types/consentflowcontract.d.ts +1 -1
- package/dist/types/credential-refresh.d.ts +10 -1
- package/dist/types/credential-refresh.d.ts.map +1 -1
- package/dist/types/inbox-batch.d.ts +38 -0
- package/dist/types/inbox-batch.d.ts.map +1 -0
- package/inbox-e2e-setup.ts +53 -1
- package/inbox-elasticmq.conf +10 -0
- package/lambda.ts +64 -16
- package/package.json +24 -16
- package/scripts/seed-demo-persona.ts +425 -0
- package/scripts/setup-inbox-queues.ts +60 -0
- package/serverless-local.yml +2 -0
- package/serverless.yml +111 -0
- package/shareLinkMaintenanceLambda.ts +49 -0
- package/src/accesslayer/auth-grant/read.ts +2 -1
- package/src/accesslayer/consentflowcontract/relationships/create.ts +9 -16
- package/src/accesslayer/consentflowcontract/relationships/update.ts +15 -28
- package/src/accesslayer/credential-activity/create.ts +1 -0
- package/src/accesslayer/credential-refresh/email-delivery.ts +116 -0
- package/src/accesslayer/credential-refresh/index.ts +1 -0
- package/src/accesslayer/credential-refresh/read.ts +8 -2
- package/src/accesslayer/credential-refresh/update.ts +4 -0
- package/src/accesslayer/inbox-batch/store.ts +469 -0
- package/src/accesslayer/inbox-credential/create.ts +51 -19
- package/src/accesslayer/inbox-credential/refresh.ts +221 -0
- package/src/accesslayer/inbox-credential/update.ts +1 -1
- package/src/accesslayer/presentation/read.ts +57 -25
- package/src/accesslayer/presentation/relationships/create.ts +54 -11
- package/src/accesslayer/presentation/relationships/read.ts +21 -6
- package/src/accesslayer/share-link/abandon.ts +100 -0
- package/src/accesslayer/share-link/cleanup.ts +271 -0
- package/src/accesslayer/share-link/errors.ts +32 -0
- package/src/accesslayer/share-link/finalize.ts +265 -0
- package/src/accesslayer/share-link/helpers.ts +419 -0
- package/src/accesslayer/share-link/index.ts +11 -0
- package/src/accesslayer/share-link/list.ts +162 -0
- package/src/accesslayer/share-link/read.ts +107 -0
- package/src/accesslayer/share-link/receipt.ts +548 -0
- package/src/accesslayer/share-link/recovery.ts +545 -0
- package/src/accesslayer/share-link/reserve.ts +684 -0
- package/src/accesslayer/share-link/revoke.ts +197 -0
- package/src/accesslayer/share-link/transaction-execution.ts +72 -0
- package/src/accesslayer/share-link/transaction.ts +126 -0
- package/src/accesslayer/share-link/types.ts +601 -0
- package/src/app.ts +6 -0
- package/src/cache/atomic-counter.test-helpers.ts +27 -0
- package/src/cache/atomic-counter.test.ts +6 -0
- package/src/cache/index.ts +25 -13
- package/src/config/environment.ts +40 -0
- package/src/constants/auth-grant.ts +5 -0
- package/src/credential-refresh.ts +5 -1
- package/src/docker-entry.ts +65 -0
- package/src/helpers/activity.helpers.ts +4 -0
- package/src/helpers/app-counter.helpers.ts +1 -1
- package/src/helpers/boost.helpers.ts +4 -31
- package/src/helpers/contact-method.helpers.test.ts +43 -0
- package/src/helpers/contact-method.helpers.ts +3 -4
- package/src/helpers/credential-refresh-email-content.helpers.test.ts +222 -0
- package/src/helpers/credential-refresh-email-content.helpers.ts +155 -0
- package/src/helpers/credential-refresh-email.helpers.ts +201 -0
- package/src/helpers/credential-refresh-proof.helpers.test.ts +103 -0
- package/src/helpers/credential-refresh-proof.helpers.ts +43 -0
- package/src/helpers/credential-refresh.helpers.ts +375 -99
- package/src/helpers/credential.helpers.ts +4 -1
- package/src/helpers/credentialSubject.helpers.test.ts +114 -0
- package/src/helpers/credentialSubject.helpers.ts +40 -0
- package/src/helpers/finalize-inbox.helpers.ts +29 -14
- package/src/helpers/inbox-batch-http.helpers.test.ts +188 -0
- package/src/helpers/inbox-batch-http.helpers.ts +150 -0
- package/src/helpers/inbox-batch-status.helpers.ts +11 -0
- package/src/helpers/inbox-batch.helpers.test.ts +668 -0
- package/src/helpers/inbox-batch.helpers.ts +374 -0
- package/src/helpers/inbox-issuance-error.helpers.ts +25 -0
- package/src/helpers/inbox-queue.helpers.test.ts +253 -0
- package/src/helpers/inbox-queue.helpers.ts +372 -0
- package/src/helpers/inbox-refresh.helpers.ts +432 -0
- package/src/helpers/inbox.helpers.ts +275 -36
- package/src/helpers/notificationMessages.ts +18 -1
- package/src/helpers/notifications.helpers.ts +4 -2
- package/src/helpers/presentation-metadata.ts +41 -0
- package/src/helpers/presentation.helpers.ts +27 -20
- package/src/helpers/profile.helpers.ts +7 -0
- package/src/helpers/rateLimit.helpers.ts +2 -5
- package/src/helpers/refresh-send-intent.helpers.ts +273 -0
- package/src/helpers/share-content-client/adapters.ts +55 -0
- package/src/helpers/share-content-client/canonical.ts +25 -0
- package/src/helpers/share-content-client/client.ts +440 -0
- package/src/helpers/share-content-client/config.ts +189 -0
- package/src/helpers/share-content-client/index.ts +27 -0
- package/src/helpers/share-content-client/responses.ts +273 -0
- package/src/helpers/share-content-client/types.ts +253 -0
- package/src/helpers/share-link-coordinator/budget-helpers.ts +53 -0
- package/src/helpers/share-link-coordinator/cleanup-runner.ts +286 -0
- package/src/helpers/share-link-coordinator/coordinator.ts +714 -0
- package/src/helpers/share-link-coordinator/index.ts +8 -0
- package/src/helpers/share-link-coordinator/recovery-runner.ts +428 -0
- package/src/helpers/share-link-coordinator/runtime.ts +88 -0
- package/src/helpers/share-link-coordinator/stat.ts +30 -0
- package/src/helpers/share-link-coordinator/types.ts +353 -0
- package/src/helpers/share-link-lifecycle/index.ts +4 -0
- package/src/helpers/share-link-lifecycle/lease.helpers.ts +35 -0
- package/src/helpers/share-link-lifecycle/recovery.helpers.ts +173 -0
- package/src/helpers/share-link-lifecycle/request-hash.helpers.ts +130 -0
- package/src/helpers/share-link-lifecycle/types.ts +58 -0
- package/src/helpers/share-link-maintenance/budget.ts +63 -0
- package/src/helpers/share-link-maintenance/config.ts +312 -0
- package/src/helpers/share-link-maintenance/index.ts +24 -0
- package/src/helpers/share-link-maintenance/runner.ts +223 -0
- package/src/helpers/share-link-maintenance/runtime.ts +334 -0
- package/src/helpers/share-link-maintenance/scheduler.ts +126 -0
- package/src/helpers/share-link-maintenance/telemetry.ts +70 -0
- package/src/helpers/share-link-maintenance/types.ts +89 -0
- package/src/helpers/share-link-owner/config.ts +48 -0
- package/src/helpers/share-link-owner/diagnostics.ts +89 -0
- package/src/helpers/share-link-owner/lazy-initializer.ts +29 -0
- package/src/helpers/share-link-owner-projection.ts +52 -0
- package/src/helpers/share-link-passcode-abuse.ts +36 -0
- package/src/helpers/share-link-passcode.ts +47 -0
- package/src/helpers/share-link-policy/index.ts +7 -0
- package/src/helpers/share-link-policy/production.ts +88 -0
- package/src/helpers/share-link-policy/resolver.ts +108 -0
- package/src/helpers/share-link-policy/types.ts +48 -0
- package/src/helpers/share-link-public/config.ts +41 -0
- package/src/helpers/share-link-view-notification.ts +18 -0
- package/src/helpers/shim.ts +32 -31
- package/src/inbox-queue-local.ts +28 -0
- package/src/models/AuthGrant.ts +1 -0
- package/src/models/CredentialActivity.ts +3 -5
- package/src/models/CredentialRefresh.ts +4 -2
- package/src/models/InboxCredential.ts +2 -0
- package/src/models/Presentation.ts +2 -2
- package/src/models/Profile.ts +3 -2
- package/src/models/ShareLink.ts +130 -0
- package/src/models/ShareViewReceipt.ts +69 -0
- package/src/models/credential-refresh-constraints.test.ts +8 -3
- package/src/models/credential-refresh-constraints.ts +5 -0
- package/src/models/index.ts +2 -0
- package/src/models/share-link-constraints.ts +93 -0
- package/src/openapi.ts +8 -0
- package/src/public-share-link-http.ts +49 -0
- package/src/routes/act-as.test.ts +239 -0
- package/src/routes/app-store.ts +4 -13
- package/src/routes/auth-grants.ts +13 -11
- package/src/routes/boosts.ts +916 -103
- package/src/routes/contracts.ts +2 -11
- package/src/routes/credential-refreshes.test.ts +8 -2
- package/src/routes/credential-refreshes.ts +4 -1
- package/src/routes/credentials.ts +2 -1
- package/src/routes/inbox.ts +95 -49
- package/src/routes/index.ts +216 -46
- package/src/routes/presentations.ts +19 -3
- package/src/routes/profile-manager.ts +10 -2
- package/src/routes/profiles.ts +17 -6
- package/src/routes/public-share-links.ts +814 -0
- package/src/routes/share-links.ts +640 -0
- package/src/routes/skills.ts +1 -1
- package/src/routes/workflows.ts +43 -24
- package/src/services/delivery/adapters/postmark.adapter.test.ts +54 -0
- package/src/services/delivery/adapters/postmark.adapter.ts +16 -1
- package/src/services/registry/registry.factory.ts +2 -1
- package/src/types/activity.ts +2 -0
- package/src/types/credential-refresh.ts +21 -2
- package/src/types/inbox-batch.ts +46 -0
- package/test/atomic-counter.e2e.ts +12 -0
- package/test/auth-grant.spec.ts +21 -21
- package/test/credential-refresh-email.spec.ts +663 -0
- package/test/credential-refresh-publication.spec.ts +2 -0
- package/test/dids.spec.ts +10 -1
- package/test/guardian-gated-routes.spec.ts +13 -0
- package/test/helpers/inbox-e2e-environment.ts +6 -0
- package/test/helpers/share-link-fixtures.ts +94 -0
- package/test/inbox-batch.spec.ts +1338 -0
- package/test/inbox-refresh.spec.ts +534 -0
- package/test/managed-recipient-inbox.spec.ts +130 -0
- package/test/notificationMessages.spec.ts +13 -0
- package/test/openapi.spec.ts +61 -1
- package/test/presentations.spec.ts +54 -6
- package/test/profiles.spec.ts +67 -1
- package/test/refresh-send.spec.ts +1799 -0
- package/test/registry.spec.ts +56 -11
- package/test/share-content-client.contract.spec.ts +365 -0
- package/test/share-content-client.unit.spec.ts +462 -0
- package/test/share-link-abuse.unit.spec.ts +65 -0
- package/test/share-link-coordinator.neo4j.spec.ts +684 -0
- package/test/share-link-coordinator.unit.spec.ts +990 -0
- package/test/share-link-dependency-diagnostics.unit.spec.ts +127 -0
- package/test/share-link-lifecycle.neo4j.spec.ts +1268 -0
- package/test/share-link-lifecycle.unit.spec.ts +205 -0
- package/test/share-link-list-cursor.unit.spec.ts +86 -0
- package/test/share-link-list.neo4j.spec.ts +324 -0
- package/test/share-link-maintenance.neo4j.spec.ts +355 -0
- package/test/share-link-maintenance.unit.spec.ts +1113 -0
- package/test/share-link-owner-policy.unit.spec.ts +210 -0
- package/test/share-link-owner-route.unit.spec.ts +752 -0
- package/test/share-link-owner-runtime.unit.spec.ts +102 -0
- package/test/share-link-passcode.unit.spec.ts +29 -0
- package/test/share-link-policy.unit.spec.ts +135 -0
- package/test/share-link-presentation-metadata.unit.spec.ts +49 -0
- package/test/share-link-production-policy.unit.spec.ts +77 -0
- package/test/share-link-public-config.unit.spec.ts +64 -0
- package/test/share-link-public-http-adapter.unit.spec.ts +315 -0
- package/test/share-link-public-route.unit.spec.ts +800 -0
- package/test/share-link-receipt.neo4j.spec.ts +943 -0
- package/test/share-link-recovery.neo4j.spec.ts +935 -0
- package/test/share-link-recovery.unit.spec.ts +726 -0
- package/vitest.config.ts +10 -0
- package/vitest.inbox-e2e.config.ts +5 -1
- package/vitest.integration.config.ts +2 -0
- package/vitest.share-links-neo4j.config.ts +19 -0
- package/vitest.share-links-unit.config.ts +28 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { SHARE_LINK_OPERATION_RETENTION_MS } from '@helpers/share-link-lifecycle';
|
|
2
|
+
|
|
3
|
+
import { ensureShareLinkConstraints } from '../../models/share-link-constraints';
|
|
4
|
+
import { failShareLink } from './errors';
|
|
5
|
+
import {
|
|
6
|
+
deleteReservation,
|
|
7
|
+
enqueueCleanupJob,
|
|
8
|
+
generateOperationId,
|
|
9
|
+
lockShare,
|
|
10
|
+
markOperationAbandoned,
|
|
11
|
+
markOperationCommitted,
|
|
12
|
+
readOperation,
|
|
13
|
+
readReservation,
|
|
14
|
+
readShareById,
|
|
15
|
+
toShareLinkOperationRecord,
|
|
16
|
+
toShareLinkRecord,
|
|
17
|
+
toShareLinkReservationRecord,
|
|
18
|
+
writeOperationInProgress,
|
|
19
|
+
type ShareLinkOperationKey,
|
|
20
|
+
} from './helpers';
|
|
21
|
+
import { withShareLinkTransaction } from './transaction';
|
|
22
|
+
import type { RevokeShareLinkInput, RevokeShareLinkResult } from './types';
|
|
23
|
+
|
|
24
|
+
const pruneAfterFrom = (now: Date): string =>
|
|
25
|
+
new Date(now.getTime() + SHARE_LINK_OPERATION_RETENTION_MS).toISOString();
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Terminally stops a share.
|
|
29
|
+
*
|
|
30
|
+
* Revoke is serialized with finalize by the same share write lock and is
|
|
31
|
+
* idempotent: once `status = 'stopped'` a retry returns the stopped share without
|
|
32
|
+
* re-checking `expectedVersion`, so a retry after the revision changed still
|
|
33
|
+
* succeeds. Stopping does not synchronously delete bytes; it queues the visible
|
|
34
|
+
* object (and any staged replacement object) for tracked cleanup and bumps the
|
|
35
|
+
* fencing generation so an in-flight finalize can no longer commit.
|
|
36
|
+
*/
|
|
37
|
+
export const revokeShareLink = async (
|
|
38
|
+
input: RevokeShareLinkInput
|
|
39
|
+
): Promise<RevokeShareLinkResult> => {
|
|
40
|
+
await ensureShareLinkConstraints();
|
|
41
|
+
|
|
42
|
+
if (input.clientRequestId && !input.requestHash) {
|
|
43
|
+
failShareLink('INVALID_INPUT', 'requestHash is required when clientRequestId is supplied');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const now = input.now ?? new Date();
|
|
47
|
+
const nowIso = now.toISOString();
|
|
48
|
+
const pruneAfter = pruneAfterFrom(now);
|
|
49
|
+
|
|
50
|
+
return withShareLinkTransaction(async tx => {
|
|
51
|
+
const lockedProps = await lockShare(tx, input.shareId);
|
|
52
|
+
|
|
53
|
+
if (!lockedProps) {
|
|
54
|
+
failShareLink('NOT_FOUND', 'share not found');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const share = toShareLinkRecord(lockedProps);
|
|
58
|
+
|
|
59
|
+
if (share.namespace !== input.namespace || share.ownerProfileId !== input.ownerProfileId) {
|
|
60
|
+
failShareLink('NOT_FOUND', 'share not found');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const operationKey: ShareLinkOperationKey | null =
|
|
64
|
+
input.clientRequestId && input.requestHash
|
|
65
|
+
? {
|
|
66
|
+
namespace: input.namespace,
|
|
67
|
+
ownerProfileId: input.ownerProfileId,
|
|
68
|
+
opKind: 'revoke',
|
|
69
|
+
clientRequestId: input.clientRequestId,
|
|
70
|
+
}
|
|
71
|
+
: null;
|
|
72
|
+
|
|
73
|
+
if (operationKey && input.requestHash) {
|
|
74
|
+
const operationProps = await readOperation(tx, operationKey);
|
|
75
|
+
|
|
76
|
+
if (operationProps) {
|
|
77
|
+
const operation = toShareLinkOperationRecord(operationProps);
|
|
78
|
+
|
|
79
|
+
if (operation.requestHash !== input.requestHash) {
|
|
80
|
+
failShareLink(
|
|
81
|
+
'CONFLICT',
|
|
82
|
+
'clientRequestId was already used with a different revoke request'
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (operation.status === 'committed') {
|
|
87
|
+
return { outcome: 'already_stopped', share, cleanupQueuedFor: [] };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (share.status === 'stopped') {
|
|
93
|
+
return { outcome: 'already_stopped', share, cleanupQueuedFor: [] };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (input.expectedVersion !== undefined && share.version !== input.expectedVersion) {
|
|
97
|
+
failShareLink(
|
|
98
|
+
'CONFLICT',
|
|
99
|
+
`expectedVersion ${input.expectedVersion} does not match the current version ${share.version}`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const cleanupRefs = new Set<string>();
|
|
104
|
+
const reservationProps = await readReservation(tx, input.shareId);
|
|
105
|
+
|
|
106
|
+
if (reservationProps) {
|
|
107
|
+
const reservation = toShareLinkReservationRecord(reservationProps);
|
|
108
|
+
|
|
109
|
+
if (reservation.objectRef) {
|
|
110
|
+
await enqueueCleanupJob(tx, {
|
|
111
|
+
objectRef: reservation.objectRef,
|
|
112
|
+
operationId: reservation.operationId,
|
|
113
|
+
namespace: reservation.namespace,
|
|
114
|
+
ownerProfileId: reservation.ownerProfileId,
|
|
115
|
+
shareId: reservation.shareId,
|
|
116
|
+
contentVersion: reservation.contentVersion ?? reservation.baseContentVersion,
|
|
117
|
+
reason: 'abandoned',
|
|
118
|
+
now: nowIso,
|
|
119
|
+
});
|
|
120
|
+
cleanupRefs.add(reservation.objectRef);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
await markOperationAbandoned(tx, {
|
|
124
|
+
namespace: reservation.namespace,
|
|
125
|
+
ownerProfileId: reservation.ownerProfileId,
|
|
126
|
+
opKind: reservation.opKind,
|
|
127
|
+
clientRequestId: reservation.clientRequestId,
|
|
128
|
+
now: nowIso,
|
|
129
|
+
});
|
|
130
|
+
await deleteReservation(tx, input.shareId);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (share.activeObjectRef) {
|
|
134
|
+
await enqueueCleanupJob(tx, {
|
|
135
|
+
objectRef: share.activeObjectRef,
|
|
136
|
+
operationId: share.activeObjectOperationId!,
|
|
137
|
+
namespace: share.namespace,
|
|
138
|
+
ownerProfileId: share.ownerProfileId,
|
|
139
|
+
shareId: share.id,
|
|
140
|
+
contentVersion: share.contentVersion,
|
|
141
|
+
reason: 'stopped',
|
|
142
|
+
now: nowIso,
|
|
143
|
+
});
|
|
144
|
+
cleanupRefs.add(share.activeObjectRef);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
await tx.run(
|
|
148
|
+
`MATCH (s:ShareLink {id: $shareId})
|
|
149
|
+
SET s.status = 'stopped',
|
|
150
|
+
s.stoppedAt = $now,
|
|
151
|
+
s.version = $version,
|
|
152
|
+
s.generation = $generation,
|
|
153
|
+
s.updatedAt = $now`,
|
|
154
|
+
{
|
|
155
|
+
shareId: input.shareId,
|
|
156
|
+
now: nowIso,
|
|
157
|
+
version: share.version + 1,
|
|
158
|
+
generation: share.generation + 1,
|
|
159
|
+
}
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
const updatedProps = await readShareById(tx, input.shareId);
|
|
163
|
+
|
|
164
|
+
if (!updatedProps) {
|
|
165
|
+
failShareLink('CONFLICT', 'share disappeared during revoke');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const updatedShare = toShareLinkRecord(updatedProps);
|
|
169
|
+
|
|
170
|
+
if (operationKey && input.requestHash) {
|
|
171
|
+
const operationId = generateOperationId();
|
|
172
|
+
|
|
173
|
+
await writeOperationInProgress(tx, {
|
|
174
|
+
...operationKey,
|
|
175
|
+
operationId,
|
|
176
|
+
shareId: input.shareId,
|
|
177
|
+
requestHash: input.requestHash,
|
|
178
|
+
now: nowIso,
|
|
179
|
+
pruneAfter,
|
|
180
|
+
});
|
|
181
|
+
await markOperationCommitted(tx, {
|
|
182
|
+
...operationKey,
|
|
183
|
+
operationId,
|
|
184
|
+
resultJson: JSON.stringify(updatedShare),
|
|
185
|
+
resultVersion: updatedShare.version,
|
|
186
|
+
now: nowIso,
|
|
187
|
+
pruneAfter,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
outcome: 'revoked',
|
|
193
|
+
share: updatedShare,
|
|
194
|
+
cleanupQueuedFor: [...cleanupRefs],
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure Neo4j transaction execution helpers.
|
|
3
|
+
*
|
|
4
|
+
* These live outside `transaction.ts` so they can be unit-tested without loading
|
|
5
|
+
* `@instance` (which requires real Neo4j environment variables at import time).
|
|
6
|
+
*
|
|
7
|
+
* The driver's managed `executeWrite` retries transient failures inline using
|
|
8
|
+
* driver-level configuration. That is correct for ordinary request callers, but a
|
|
9
|
+
* cooperative maintenance pass instead wants one bounded attempt: if it cannot
|
|
10
|
+
* commit now it leaves the durable work fenced and lets the next cadence retry.
|
|
11
|
+
* `executeExplicitTransaction` provides exactly that explicit, no-inline-retry
|
|
12
|
+
* attempt.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Minimal structural transaction surface shared by managed and explicit paths. */
|
|
16
|
+
export type ExecutableTransaction = {
|
|
17
|
+
run: (query: string, params?: Record<string, unknown>) => Promise<unknown>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type ExplicitTransaction = ExecutableTransaction & {
|
|
21
|
+
commit: () => Promise<void>;
|
|
22
|
+
rollback: () => Promise<void>;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** The subset of the neo4j-driver session API this module depends on. */
|
|
26
|
+
export type TransactionSession = {
|
|
27
|
+
beginTransaction: (config?: { timeout?: number }) => ExplicitTransaction;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type TransactionTimeoutConfig = { timeout: number } | undefined;
|
|
31
|
+
|
|
32
|
+
export const resolveTransactionConfig = (
|
|
33
|
+
timeoutMs: number | undefined
|
|
34
|
+
): TransactionTimeoutConfig =>
|
|
35
|
+
typeof timeoutMs === 'number' && Number.isFinite(timeoutMs) && timeoutMs > 0
|
|
36
|
+
? { timeout: Math.trunc(timeoutMs) }
|
|
37
|
+
: undefined;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Run one explicit transaction attempt with a bounded server-side timeout.
|
|
41
|
+
*
|
|
42
|
+
* There is deliberately no retry: a transient failure propagates to the caller,
|
|
43
|
+
* which records a bounded category and leaves the durable claim/job for the next
|
|
44
|
+
* cadence. The callback must only perform graph-local work — no network I/O — so
|
|
45
|
+
* a rollback can never strand a remote mutation.
|
|
46
|
+
*/
|
|
47
|
+
export const executeExplicitTransaction = async <T>(
|
|
48
|
+
session: TransactionSession,
|
|
49
|
+
work: (tx: ExecutableTransaction) => Promise<T>,
|
|
50
|
+
timeoutMs?: number
|
|
51
|
+
): Promise<T> => {
|
|
52
|
+
const transaction = session.beginTransaction(resolveTransactionConfig(timeoutMs));
|
|
53
|
+
|
|
54
|
+
let result: T;
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
result = await work(transaction);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
try {
|
|
60
|
+
await transaction.rollback();
|
|
61
|
+
} catch {
|
|
62
|
+
// The transaction may already be terminated (e.g. timeout). The
|
|
63
|
+
// original failure is authoritative.
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
await transaction.commit();
|
|
70
|
+
|
|
71
|
+
return result;
|
|
72
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { neogma } from '@instance';
|
|
2
|
+
|
|
3
|
+
import { ShareLinkRepositoryError } from './errors';
|
|
4
|
+
import {
|
|
5
|
+
executeExplicitTransaction,
|
|
6
|
+
resolveTransactionConfig,
|
|
7
|
+
type TransactionSession,
|
|
8
|
+
} from './transaction-execution';
|
|
9
|
+
|
|
10
|
+
/** Neo4j signals a uniqueness race as a client error; map it to a typed conflict. */
|
|
11
|
+
const isNeo4jConstraintViolation = (error: unknown): boolean => {
|
|
12
|
+
const code = (error as { code?: string } | undefined)?.code;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
code === 'Neo.ClientError.Schema.ConstraintValidationFailed' ||
|
|
16
|
+
code === 'Neo.ClientError.Statement.ConstraintVerificationFailed'
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** Minimal structural result shape used by the lifecycle Cypher helpers. */
|
|
21
|
+
export type Neo4jQueryResult = {
|
|
22
|
+
records: Array<{
|
|
23
|
+
get: (key: string) => unknown;
|
|
24
|
+
}>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** The subset of the neo4j-driver transaction API the repository depends on. */
|
|
28
|
+
export interface ShareLinkTransaction {
|
|
29
|
+
run: (query: string, params?: Record<string, unknown>) => Promise<Neo4jQueryResult>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Narrow, opt-in transaction bounds.
|
|
34
|
+
*
|
|
35
|
+
* When omitted (every existing caller), the managed write transaction keeps the
|
|
36
|
+
* driver defaults exactly as before. A maintenance caller may set `timeoutMs` so
|
|
37
|
+
* a single transaction cannot outlive its declared pass budget; it does not
|
|
38
|
+
* change the retry behaviour or any other caller.
|
|
39
|
+
*/
|
|
40
|
+
export type ShareLinkTransactionOptions = {
|
|
41
|
+
/** Neo4j managed-transaction timeout in milliseconds. */
|
|
42
|
+
timeoutMs?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Maintenance-only mode: run a single explicit transaction with the supplied
|
|
45
|
+
* timeout and NO driver-managed inline retry. Ordinary callers omit this and
|
|
46
|
+
* keep the existing managed retry defaults; a maintenance pass leaves retry to
|
|
47
|
+
* the next scheduler cadence.
|
|
48
|
+
*/
|
|
49
|
+
noInlineRetry?: boolean;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Runs a read unit either through the shared auto-commit query runner (ordinary
|
|
54
|
+
* callers, unchanged) or, when a maintenance bound is supplied, through a single
|
|
55
|
+
* explicit read transaction with that timeout. No inline retry is used in the
|
|
56
|
+
* bounded path.
|
|
57
|
+
*/
|
|
58
|
+
export const withShareLinkRead = async <T>(
|
|
59
|
+
work: (runner: ShareLinkTransaction) => Promise<T>,
|
|
60
|
+
options?: ShareLinkTransactionOptions
|
|
61
|
+
): Promise<T> => {
|
|
62
|
+
if (options?.noInlineRetry !== true && options?.timeoutMs === undefined) {
|
|
63
|
+
return work(neogma.queryRunner as unknown as ShareLinkTransaction);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const session = neogma.queryRunner.getDriver().session();
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
return await executeExplicitTransaction<T>(
|
|
70
|
+
session as unknown as TransactionSession,
|
|
71
|
+
tx => work(tx as unknown as ShareLinkTransaction),
|
|
72
|
+
options?.timeoutMs
|
|
73
|
+
);
|
|
74
|
+
} finally {
|
|
75
|
+
await session.close();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Runs a unit of share-link lifecycle work inside one managed Neo4j write transaction.
|
|
81
|
+
*
|
|
82
|
+
* The repository deliberately uses a managed write transaction rather than a sequence
|
|
83
|
+
* of auto-committed statements: the share write lock acquired by the first
|
|
84
|
+
* statement must cover every subsequent read of status/version/reservation state
|
|
85
|
+
* and the final writes. A rollback aborts the whole unit, so a partial finalize
|
|
86
|
+
* (metadata swapped without the cleanup job, or vice versa) is impossible.
|
|
87
|
+
*
|
|
88
|
+
* Reads that only need a committed snapshot use the auto-committed `queryRunner`
|
|
89
|
+
* helpers instead; this wrapper is for mutations.
|
|
90
|
+
*/
|
|
91
|
+
export const withShareLinkTransaction = async <T>(
|
|
92
|
+
work: (tx: ShareLinkTransaction) => Promise<T>,
|
|
93
|
+
options?: ShareLinkTransactionOptions
|
|
94
|
+
): Promise<T> => {
|
|
95
|
+
const session = neogma.queryRunner.getDriver().session();
|
|
96
|
+
try {
|
|
97
|
+
if (options?.noInlineRetry === true) {
|
|
98
|
+
// One explicit, bounded attempt with no inline retry.
|
|
99
|
+
return await executeExplicitTransaction<T>(
|
|
100
|
+
session as unknown as TransactionSession,
|
|
101
|
+
tx => work(tx as unknown as ShareLinkTransaction),
|
|
102
|
+
options.timeoutMs
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Managed writes retry transient Neo4j deadlocks. Callback work must be
|
|
107
|
+
// graph-local: no remote uploads or deletes inside the transaction.
|
|
108
|
+
const transactionConfig = resolveTransactionConfig(options?.timeoutMs);
|
|
109
|
+
|
|
110
|
+
return await session.executeWrite(
|
|
111
|
+
tx => work(tx as unknown as ShareLinkTransaction),
|
|
112
|
+
transactionConfig
|
|
113
|
+
);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (isNeo4jConstraintViolation(error)) {
|
|
116
|
+
throw new ShareLinkRepositoryError(
|
|
117
|
+
'CONFLICT',
|
|
118
|
+
'a concurrent share-link write violated a uniqueness rule'
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
throw error;
|
|
123
|
+
} finally {
|
|
124
|
+
await session.close();
|
|
125
|
+
}
|
|
126
|
+
};
|