@learncard/network-brain-service 3.19.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 +34 -2
- package/CHANGELOG.md +38 -0
- package/README.md +42 -0
- 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/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/config/environment.d.ts +9 -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/helpers/boost.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/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/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/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/index.js +2 -2
- 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/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/public-share-link-http.d.ts +4 -0
- package/dist/public-share-link-http.d.ts.map +1 -0
- package/dist/routes/app-store.d.ts.map +1 -1
- 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/credentials.d.ts +1 -1
- package/dist/routes/index.d.ts +153 -0
- 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/services/delivery/adapters/postmark.adapter.d.ts.map +1 -1
- package/dist/types/consentflowcontract.d.ts +1 -1
- package/lambda.ts +4 -1
- package/package.json +22 -16
- package/scripts/seed-demo-persona.ts +425 -0
- package/serverless.yml +36 -0
- package/shareLinkMaintenanceLambda.ts +49 -0
- package/src/accesslayer/consentflowcontract/relationships/create.ts +9 -16
- package/src/accesslayer/consentflowcontract/relationships/update.ts +15 -28
- 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/config/environment.ts +14 -0
- package/src/constants/auth-grant.ts +5 -0
- package/src/docker-entry.ts +57 -0
- package/src/helpers/boost.helpers.ts +4 -31
- package/src/helpers/credentialSubject.helpers.test.ts +114 -0
- package/src/helpers/credentialSubject.helpers.ts +40 -0
- package/src/helpers/inbox.helpers.ts +7 -4
- package/src/helpers/notificationMessages.ts +18 -1
- 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/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/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/index.ts +2 -0
- package/src/models/share-link-constraints.ts +93 -0
- package/src/public-share-link-http.ts +49 -0
- package/src/routes/app-store.ts +2 -11
- package/src/routes/boosts.ts +2 -11
- package/src/routes/contracts.ts +2 -11
- package/src/routes/index.ts +139 -44
- 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/services/delivery/adapters/postmark.adapter.ts +4 -1
- package/test/dids.spec.ts +10 -1
- package/test/guardian-gated-routes.spec.ts +13 -0
- package/test/helpers/share-link-fixtures.ts +94 -0
- package/test/managed-recipient-inbox.spec.ts +130 -0
- package/test/notificationMessages.spec.ts +13 -0
- package/test/openapi.spec.ts +20 -0
- package/test/presentations.spec.ts +54 -6
- package/test/profiles.spec.ts +67 -1
- 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 +1 -0
- package/vitest.share-links-neo4j.config.ts +19 -0
- package/vitest.share-links-unit.config.ts +28 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"share-links.d.ts","sourceRoot":"","sources":["../../src/routes/share-links.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EACR,0BAA0B,EAC1B,oBAAoB,EAEvB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,KAAK,EACR,mBAAmB,EACnB,oBAAoB,EAEvB,MAAM,+BAA+B,CAAC;AAYvC,MAAM,MAAM,2BAA2B,GAAG;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;IAC3C,QAAQ,CAAC,QAAQ,EAAE,0BAA0B,CAAC;IAM9C,QAAQ,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;IAEvF,QAAQ,CAAC,0BAA0B,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAM/E,QAAQ,CAAC,8BAA8B,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACzF,CAAC;AAgHF,eAAO,MAAM,sBAAsB,GAC/B,iBAAiB,MAAM,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuVrE,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAGzE,eAAO,MAAM,+BAA+B,GACxC,WAAW,MAAM,EACjB,gBAAgB,MAAM,KACvB,OAAO,CAAC,IAAI,CASd,CAAC;AAkBF,eAAO,MAAM,yBAAyB,mDAOhC,CAAC;AAoEP,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAAoD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postmark.adapter.d.ts","sourceRoot":"","sources":["../../../../src/services/delivery/adapters/postmark.adapter.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAwCpE,qBAAa,eAAgB,YAAW,eAAe;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAE1B,MAAM,EAAE,MAAM;IAIb,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAwF5D,OAAO,CAAC,gBAAgB;
|
|
1
|
+
{"version":3,"file":"postmark.adapter.d.ts","sourceRoot":"","sources":["../../../../src/services/delivery/adapters/postmark.adapter.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAwCpE,qBAAa,eAAgB,YAAW,eAAe;IACnD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAE1B,MAAM,EAAE,MAAM;IAIb,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAwF5D,OAAO,CAAC,gBAAgB;CAiG3B"}
|
|
@@ -96,8 +96,8 @@ export type FlatDbTransactionType = Omit<DbTransactionType, 'guardianApproval' |
|
|
|
96
96
|
export declare const DbTermsValidator: z.ZodObject<{
|
|
97
97
|
id: z.ZodString;
|
|
98
98
|
status: z.ZodEnum<{
|
|
99
|
-
live: "live";
|
|
100
99
|
stale: "stale";
|
|
100
|
+
live: "live";
|
|
101
101
|
withdrawn: "withdrawn";
|
|
102
102
|
}>;
|
|
103
103
|
terms: z.ZodPrefault<z.ZodObject<{
|
package/lambda.ts
CHANGED
|
@@ -14,6 +14,7 @@ import skillsViewerApp from './src/skills-viewer';
|
|
|
14
14
|
import statusListsApp from './src/status-lists';
|
|
15
15
|
import credentialRefreshApp from './src/credential-refresh';
|
|
16
16
|
import { appRouter, createContext } from './src/app';
|
|
17
|
+
import { publicShareLinkCacheControlHeaders } from './src/routes';
|
|
17
18
|
import { deliverQueuedNotification } from './src/helpers/notificationQueue.helpers';
|
|
18
19
|
import { startSkillEmbeddingBackfill } from './src/helpers/skill-embedding.helpers';
|
|
19
20
|
import { createOpenApiAwsLambdaHandler } from './src/helpers/shim';
|
|
@@ -72,6 +73,7 @@ export const _openApiHandler = createOpenApiAwsLambdaHandler({
|
|
|
72
73
|
'Access-Control-Allow-Origin': '*',
|
|
73
74
|
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
|
74
75
|
'Access-Control-Allow-Headers': 'Authorization, Content-Type',
|
|
76
|
+
...publicShareLinkCacheControlHeaders(meta.paths),
|
|
75
77
|
},
|
|
76
78
|
};
|
|
77
79
|
},
|
|
@@ -85,12 +87,13 @@ export const _trpcHandler = withInboxBatchBodyLimit(
|
|
|
85
87
|
router: appRouter,
|
|
86
88
|
createContext,
|
|
87
89
|
onError: handleTrpcError,
|
|
88
|
-
responseMeta: () => {
|
|
90
|
+
responseMeta: ({ paths }) => {
|
|
89
91
|
return {
|
|
90
92
|
headers: {
|
|
91
93
|
'Access-Control-Allow-Origin': '*',
|
|
92
94
|
'Access-Control-Allow-Methods': '*',
|
|
93
95
|
'Access-Control-Allow-Headers': 'authorization',
|
|
96
|
+
...publicShareLinkCacheControlHeaders(paths),
|
|
94
97
|
},
|
|
95
98
|
};
|
|
96
99
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@learncard/network-brain-service",
|
|
3
|
-
"version": "3.19.
|
|
3
|
+
"version": "3.19.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=24.12 <25"
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"test:integration:watch": "vitest --config vitest.integration.config.ts",
|
|
20
20
|
"test:docker": "vitest run --config vitest.integration.config.ts",
|
|
21
21
|
"seed:dev-app": "bun scripts/seed-dev-app.ts",
|
|
22
|
+
"seed:demo-persona": "bun --conditions=development scripts/seed-demo-persona.ts",
|
|
22
23
|
"skill-frameworks": "bun scripts/skill-frameworks.ts",
|
|
23
24
|
"build": "shx rm -rf dist && node bundle.mjs && tsc --p tsconfig.build.json && tsc --showConfig --p tsconfig.build.json > tsconfig.temp.json && tsc-alias --replacer ./tsc-alias-replacer.cjs -p tsconfig.temp.json && shx rm tsconfig.temp.json",
|
|
24
25
|
"typecheck": "tsc --noEmit -p tsconfig.build.json && tsc --noEmit -p tsconfig.entrypoints.json",
|
|
@@ -61,27 +62,30 @@
|
|
|
61
62
|
"@digitalcredentials/issuer-registry-client": "^3.2.0-beta.5",
|
|
62
63
|
"@fastify/cors": "^11.2.0",
|
|
63
64
|
"@google/genai": "^1.27.0",
|
|
64
|
-
"@learncard/
|
|
65
|
-
"@learncard/
|
|
66
|
-
"@learncard/
|
|
67
|
-
"@learncard/
|
|
68
|
-
"@learncard/
|
|
69
|
-
"@learncard/didkit-plugin
|
|
70
|
-
"@learncard/
|
|
71
|
-
"@learncard/
|
|
72
|
-
"@learncard/
|
|
73
|
-
"@learncard/
|
|
74
|
-
"@learncard/
|
|
75
|
-
"@learncard/
|
|
76
|
-
"@learncard/
|
|
77
|
-
"@learncard/
|
|
78
|
-
"@learncard/vc-
|
|
65
|
+
"@learncard/credential-library": "2.0.5",
|
|
66
|
+
"@learncard/core": "9.4.37",
|
|
67
|
+
"@learncard/crypto-plugin": "1.1.37",
|
|
68
|
+
"@learncard/did-web-plugin": "1.1.37",
|
|
69
|
+
"@learncard/didkey-plugin": "1.1.37",
|
|
70
|
+
"@learncard/didkit-plugin": "1.10.2",
|
|
71
|
+
"@learncard/didkit-plugin-node": "0.3.2",
|
|
72
|
+
"@learncard/dynamic-loader-plugin": "1.1.37",
|
|
73
|
+
"@learncard/encryption-plugin": "1.1.37",
|
|
74
|
+
"@learncard/expiration-plugin": "1.2.37",
|
|
75
|
+
"@learncard/email-templates": "1.2.0",
|
|
76
|
+
"@learncard/helpers": "1.6.1",
|
|
77
|
+
"@learncard/learn-card-plugin": "1.2.37",
|
|
78
|
+
"@learncard/types": "5.22.0",
|
|
79
|
+
"@learncard/vc-plugin": "1.6.3",
|
|
80
|
+
"@learncard/vc-templates-plugin": "1.1.37",
|
|
79
81
|
"@sentry/serverless": "7.61.0",
|
|
80
82
|
"@trpc/server": "11.8.0",
|
|
81
83
|
"@types/lodash": "^4.14.191",
|
|
82
84
|
"base64url": "^3.0.1",
|
|
85
|
+
"bs58": "^5.0.0",
|
|
83
86
|
"cors": "^2.8.5",
|
|
84
87
|
"dotenv": "^16.0.3",
|
|
88
|
+
"hash-wasm": "^4.12.0",
|
|
85
89
|
"express": "^4.18.2",
|
|
86
90
|
"fastify": "^5.8.5",
|
|
87
91
|
"fastify-plugin": "^5.1.0",
|
|
@@ -93,6 +97,7 @@
|
|
|
93
97
|
"lodash": "^4.17.21",
|
|
94
98
|
"messagebird": "^4.0.1",
|
|
95
99
|
"multiformats": "^11.0.1",
|
|
100
|
+
"mongodb": "^6.2.0",
|
|
96
101
|
"mustache": "^4.2.0",
|
|
97
102
|
"neo4j-driver": "5.18.0",
|
|
98
103
|
"neogma": "1.13.0",
|
|
@@ -103,6 +108,7 @@
|
|
|
103
108
|
"tsc-alias": "^1.8.10",
|
|
104
109
|
"twilio": "^5.7.1",
|
|
105
110
|
"undici": "^6",
|
|
111
|
+
"tweetnacl": "^1.0.3",
|
|
106
112
|
"uuid": "^14.0.0",
|
|
107
113
|
"zod": "4.4.3",
|
|
108
114
|
"zod-openapi": "^5.0.1"
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Publish a credential-library persona as a ConsentFlow contract with auto-boosts.
|
|
4
|
+
*
|
|
5
|
+
* Usage (from services/learn-card-network/brain-service):
|
|
6
|
+
* bun run seed:demo-persona student
|
|
7
|
+
*
|
|
8
|
+
* The script is idempotent: profile, signing authority, Boost, contract, and
|
|
9
|
+
* AUTO_RECEIVE identifiers are stable. Re-running updates fixture content and
|
|
10
|
+
* replaces the contract's auto-boost set without changing its URI.
|
|
11
|
+
*
|
|
12
|
+
* Every target requires explicit database, domain, signing-authority endpoint,
|
|
13
|
+
* and 64-character signing seed configuration.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
17
|
+
import { createHmac } from 'node:crypto';
|
|
18
|
+
|
|
19
|
+
import * as bs58 from 'bs58';
|
|
20
|
+
import * as dotenv from 'dotenv';
|
|
21
|
+
import { MongoClient } from 'mongodb';
|
|
22
|
+
import { Neogma } from 'neogma';
|
|
23
|
+
import Redis from 'ioredis';
|
|
24
|
+
import * as nacl from 'tweetnacl';
|
|
25
|
+
import { v4 as uuid, v5 as uuidv5 } from 'uuid';
|
|
26
|
+
|
|
27
|
+
import {
|
|
28
|
+
getBundle,
|
|
29
|
+
getFixture,
|
|
30
|
+
prepareFixture,
|
|
31
|
+
type CredentialBundleEntry,
|
|
32
|
+
type CredentialBundleIssuer,
|
|
33
|
+
} from '@learncard/credential-library';
|
|
34
|
+
import type { UnsignedVC } from '@learncard/types';
|
|
35
|
+
import { flattenObject } from '../src/helpers/objects.helpers';
|
|
36
|
+
|
|
37
|
+
dotenv.config({ path: fileURLToPath(new URL('../.env', import.meta.url)) });
|
|
38
|
+
|
|
39
|
+
const PERSONA_NAMESPACE = '5c4bb193-6e65-43d9-940d-d85b758a94f2';
|
|
40
|
+
const SIGNING_AUTHORITY_NAME = 'sample-personas';
|
|
41
|
+
|
|
42
|
+
const NEO4J_URI = process.env.NEO4J_URI ?? 'bolt://localhost:7687';
|
|
43
|
+
const NEO4J_USERNAME = process.env.NEO4J_USERNAME ?? 'neo4j';
|
|
44
|
+
const NEO4J_PASSWORD = process.env.NEO4J_PASSWORD ?? 'this-is-the-password';
|
|
45
|
+
const MONGO_URI = process.env.MONGO_URI ?? 'mongodb://localhost:27017/?replicaSet=rs0';
|
|
46
|
+
const MONGO_DB_NAME = process.env.MONGO_DB_NAME ?? 'lca-api';
|
|
47
|
+
const REDIS_HOST = process.env.REDIS_HOST ?? 'localhost';
|
|
48
|
+
const REDIS_PORT = Number.parseInt(process.env.REDIS_PORT ?? '6379', 10);
|
|
49
|
+
const BRAIN_DOMAIN = process.env.DOMAIN_NAME || 'localhost%3A4000';
|
|
50
|
+
const SIGNING_AUTHORITY_ENDPOINT = process.env.DEMO_PERSONA_SIGNING_AUTHORITY_ENDPOINT;
|
|
51
|
+
const SIGNING_AUTHORITY_SEED = process.env.DEMO_PERSONA_SA_SEED;
|
|
52
|
+
|
|
53
|
+
const personaId = process.argv[2];
|
|
54
|
+
|
|
55
|
+
if (!personaId) {
|
|
56
|
+
throw new Error('Usage: bun scripts/seed-demo-persona.ts <personaId>');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!SIGNING_AUTHORITY_SEED || !SIGNING_AUTHORITY_ENDPOINT) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
'DEMO_PERSONA_SA_SEED and DEMO_PERSONA_SIGNING_AUTHORITY_ENDPOINT are required.'
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!/^[0-9a-f]{64}$/i.test(SIGNING_AUTHORITY_SEED)) {
|
|
66
|
+
throw new Error('DEMO_PERSONA_SA_SEED must contain exactly 64 hexadecimal characters.');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const transformProfileId = (raw: string): string => raw.toLowerCase().replace(/:/g, '%3A');
|
|
70
|
+
|
|
71
|
+
const getDidWeb = (domain: string, profileId: string): string =>
|
|
72
|
+
`did:web:${domain}:users:${profileId}`;
|
|
73
|
+
|
|
74
|
+
const constructContractUri = (contractId: string): string => {
|
|
75
|
+
const encodedDomain = BRAIN_DOMAIN.includes('localhost')
|
|
76
|
+
? BRAIN_DOMAIN.replace(/:/g, '%3A')
|
|
77
|
+
: BRAIN_DOMAIN.replace(/:/g, '/');
|
|
78
|
+
|
|
79
|
+
return `lc:network:${encodedDomain.replace(/\/trpc$/, '')}/trpc:contract:${contractId}`;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const deriveDidKeyFromSeed = (hexSeed: string): string => {
|
|
83
|
+
const seedBytes = Buffer.from(hexSeed, 'hex');
|
|
84
|
+
const keyPair = nacl.sign.keyPair.fromSeed(seedBytes);
|
|
85
|
+
const multicodec = Buffer.concat([Buffer.from('ed01', 'hex'), Buffer.from(keyPair.publicKey)]);
|
|
86
|
+
|
|
87
|
+
return `did:key:z${bs58.encode(multicodec)}`;
|
|
88
|
+
};
|
|
89
|
+
const deriveSigningAuthoritySeed = (profileId: string): string =>
|
|
90
|
+
createHmac('sha256', Buffer.from(SIGNING_AUTHORITY_SEED, 'hex'))
|
|
91
|
+
.update(`learncard:sample-persona:${profileId}`)
|
|
92
|
+
.digest('hex');
|
|
93
|
+
|
|
94
|
+
const clearProfileDidDocumentCache = async (profileId: string): Promise<void> => {
|
|
95
|
+
const redis = new Redis({
|
|
96
|
+
host: REDIS_HOST,
|
|
97
|
+
port: REDIS_PORT,
|
|
98
|
+
lazyConnect: true,
|
|
99
|
+
connectTimeout: 2_000,
|
|
100
|
+
retryStrategy: () => null,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
await redis.connect();
|
|
105
|
+
await redis.del(`did-doc:${profileId}`);
|
|
106
|
+
} catch {
|
|
107
|
+
console.warn(
|
|
108
|
+
`Could not clear did-doc:${profileId} at ${REDIS_HOST}:${REDIS_PORT}; delete that Redis key manually, or restart the brain service if it uses an in-memory cache.`
|
|
109
|
+
);
|
|
110
|
+
} finally {
|
|
111
|
+
redis.disconnect();
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const shiftDate = (offsetDays: number): string => {
|
|
116
|
+
const date = new Date();
|
|
117
|
+
date.setUTCDate(date.getUTCDate() + offsetDays);
|
|
118
|
+
return date.toISOString();
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const prepareBundleCredential = (entry: CredentialBundleEntry, issuerDid: string): UnsignedVC => {
|
|
122
|
+
const fixture = getFixture(entry.fixtureId);
|
|
123
|
+
const prepared = prepareFixture(fixture, {
|
|
124
|
+
issuerDid,
|
|
125
|
+
subjectDid: 'did:example:123',
|
|
126
|
+
validFrom: shiftDate(entry.validFromOffsetDays),
|
|
127
|
+
freshIds: false,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
if (entry.name) prepared.name = entry.name;
|
|
131
|
+
|
|
132
|
+
return prepared;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const toBoostTemplate = (credential: UnsignedVC, issuerDid: string): string => {
|
|
136
|
+
const template = structuredClone(credential) as Record<string, unknown>;
|
|
137
|
+
delete template.id;
|
|
138
|
+
delete template.proof;
|
|
139
|
+
template.issuer = issuerDid;
|
|
140
|
+
|
|
141
|
+
const subjects = Array.isArray(template.credentialSubject)
|
|
142
|
+
? template.credentialSubject
|
|
143
|
+
: [template.credentialSubject];
|
|
144
|
+
for (const subject of subjects) {
|
|
145
|
+
if (subject && typeof subject === 'object') {
|
|
146
|
+
Object.assign(subject, { id: 'did:example:123' });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return JSON.stringify(template);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const ensureSigningAuthority = async (
|
|
154
|
+
ownerDid: string,
|
|
155
|
+
did: string,
|
|
156
|
+
seed: string
|
|
157
|
+
): Promise<void> => {
|
|
158
|
+
const client = new MongoClient(MONGO_URI);
|
|
159
|
+
|
|
160
|
+
try {
|
|
161
|
+
await client.connect();
|
|
162
|
+
await client
|
|
163
|
+
.db(MONGO_DB_NAME)
|
|
164
|
+
.collection('signingauthorities')
|
|
165
|
+
.updateOne(
|
|
166
|
+
{ ownerDid, name: SIGNING_AUTHORITY_NAME },
|
|
167
|
+
{
|
|
168
|
+
$set: { seed, did },
|
|
169
|
+
$setOnInsert: { _id: uuid(), ownerDid, name: SIGNING_AUTHORITY_NAME },
|
|
170
|
+
},
|
|
171
|
+
{ upsert: true }
|
|
172
|
+
);
|
|
173
|
+
} finally {
|
|
174
|
+
await client.close();
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const main = async (): Promise<void> => {
|
|
179
|
+
const bundle = getBundle(personaId);
|
|
180
|
+
const [firstEntry] = bundle.entries;
|
|
181
|
+
if (!firstEntry) {
|
|
182
|
+
throw new Error(`Credential bundle ${bundle.id} has no entries.`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const issuerProfiles = new Map<
|
|
186
|
+
string,
|
|
187
|
+
CredentialBundleIssuer & {
|
|
188
|
+
profileId: `sample-${string}`;
|
|
189
|
+
did: string;
|
|
190
|
+
signingAuthorityDid: string;
|
|
191
|
+
signingAuthoritySeed: string;
|
|
192
|
+
}
|
|
193
|
+
>();
|
|
194
|
+
for (const entry of bundle.entries) {
|
|
195
|
+
const profileId = transformProfileId(entry.issuer.profileId);
|
|
196
|
+
if (!profileId.startsWith('sample-')) {
|
|
197
|
+
throw new Error(`Refusing to seed non-sample issuer profile: ${profileId}`);
|
|
198
|
+
}
|
|
199
|
+
const existingIssuer = issuerProfiles.get(profileId);
|
|
200
|
+
|
|
201
|
+
if (
|
|
202
|
+
existingIssuer &&
|
|
203
|
+
(existingIssuer.displayName !== entry.issuer.displayName ||
|
|
204
|
+
existingIssuer.image !== entry.issuer.image)
|
|
205
|
+
) {
|
|
206
|
+
throw new Error(`Conflicting metadata configured for sample issuer ${profileId}.`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const signingAuthoritySeed = deriveSigningAuthoritySeed(profileId);
|
|
210
|
+
const signingAuthorityDid = deriveDidKeyFromSeed(signingAuthoritySeed);
|
|
211
|
+
issuerProfiles.set(profileId, {
|
|
212
|
+
...entry.issuer,
|
|
213
|
+
profileId: profileId as `sample-${string}`,
|
|
214
|
+
did: getDidWeb(BRAIN_DOMAIN, profileId),
|
|
215
|
+
signingAuthorityDid,
|
|
216
|
+
signingAuthoritySeed,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const contractOwnerProfileId = transformProfileId(firstEntry.issuer.profileId);
|
|
221
|
+
const contractId = uuidv5(`persona:${bundle.id}:contract`, PERSONA_NAMESPACE);
|
|
222
|
+
const neogma = new Neogma({
|
|
223
|
+
url: NEO4J_URI,
|
|
224
|
+
username: NEO4J_USERNAME,
|
|
225
|
+
password: NEO4J_PASSWORD,
|
|
226
|
+
});
|
|
227
|
+
const run = neogma.queryRunner.run.bind(neogma.queryRunner);
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
for (const issuer of issuerProfiles.values()) {
|
|
231
|
+
const profileResult = await run(
|
|
232
|
+
`MERGE (p:Profile {profileId: $profileId})
|
|
233
|
+
ON CREATE SET p.isSamplePersona = true
|
|
234
|
+
WITH p
|
|
235
|
+
WHERE p.isSamplePersona = true
|
|
236
|
+
AND (p.did IS NULL OR p.did = $did)
|
|
237
|
+
SET p.displayName = $displayName,
|
|
238
|
+
p.shortBio = $shortBio,
|
|
239
|
+
p.image = $image,
|
|
240
|
+
p.did = $did
|
|
241
|
+
RETURN p.did AS did`,
|
|
242
|
+
{
|
|
243
|
+
profileId: issuer.profileId,
|
|
244
|
+
displayName: issuer.displayName,
|
|
245
|
+
shortBio: 'Issuer for LearnCard sample credentials',
|
|
246
|
+
image: issuer.image ?? '',
|
|
247
|
+
did: issuer.signingAuthorityDid,
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
const storedSigningAuthorityDid = profileResult.records[0]?.get('did');
|
|
251
|
+
if (!storedSigningAuthorityDid) {
|
|
252
|
+
throw new Error(
|
|
253
|
+
`Refusing to overwrite existing non-sample profile ${issuer.profileId}.`
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
if (storedSigningAuthorityDid !== issuer.signingAuthorityDid) {
|
|
257
|
+
throw new Error(
|
|
258
|
+
`Profile ${issuer.profileId} did not retain its signing authority DID.`
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
await run(
|
|
263
|
+
`MERGE (sa:SigningAuthority {endpoint: $endpoint})
|
|
264
|
+
WITH sa
|
|
265
|
+
MATCH (p:Profile {profileId: $profileId})
|
|
266
|
+
MERGE (p)-[r:USES_SIGNING_AUTHORITY {name: $name}]->(sa)
|
|
267
|
+
SET r.did = $did, r.isPrimary = true
|
|
268
|
+
RETURN r`,
|
|
269
|
+
{
|
|
270
|
+
endpoint: SIGNING_AUTHORITY_ENDPOINT,
|
|
271
|
+
profileId: issuer.profileId,
|
|
272
|
+
name: SIGNING_AUTHORITY_NAME,
|
|
273
|
+
did: issuer.signingAuthorityDid,
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
await clearProfileDidDocumentCache(issuer.profileId);
|
|
277
|
+
await ensureSigningAuthority(
|
|
278
|
+
issuer.did,
|
|
279
|
+
issuer.signingAuthorityDid,
|
|
280
|
+
issuer.signingAuthoritySeed
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const autoBoosts: Array<{ boostId: string; issuerProfileId: string }> = [];
|
|
285
|
+
for (const entry of bundle.entries) {
|
|
286
|
+
const fixture = getFixture(entry.fixtureId);
|
|
287
|
+
const profileId = transformProfileId(entry.issuer.profileId);
|
|
288
|
+
const issuer = issuerProfiles.get(profileId);
|
|
289
|
+
if (!issuer) {
|
|
290
|
+
throw new Error(`Missing seeded issuer profile ${profileId}.`);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const boostId = uuidv5(
|
|
294
|
+
`persona:${bundle.id}:fixture:${entry.fixtureId}`,
|
|
295
|
+
PERSONA_NAMESPACE
|
|
296
|
+
);
|
|
297
|
+
const credential = prepareBundleCredential(entry, issuer.did);
|
|
298
|
+
const boost = toBoostTemplate(credential, issuer.did);
|
|
299
|
+
autoBoosts.push({ boostId, issuerProfileId: profileId });
|
|
300
|
+
const boostProperties = flattenObject({
|
|
301
|
+
id: boostId,
|
|
302
|
+
boost,
|
|
303
|
+
name: entry.name ?? fixture.name,
|
|
304
|
+
type: fixture.profile,
|
|
305
|
+
category: 'Achievement',
|
|
306
|
+
status: 'LIVE',
|
|
307
|
+
meta: { personaId: bundle.id, fixtureId: fixture.id },
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
const boostResult = await run(
|
|
311
|
+
`MERGE (b:Boost {id: $boostId})
|
|
312
|
+
SET b = $properties
|
|
313
|
+
WITH b
|
|
314
|
+
OPTIONAL MATCH (b)-[oldCreated:CREATED_BY]->(:Profile)
|
|
315
|
+
DELETE oldCreated
|
|
316
|
+
WITH DISTINCT b
|
|
317
|
+
OPTIONAL MATCH (:Profile)-[oldRole:HAS_ROLE {roleId: '__creator__'}]->(b)
|
|
318
|
+
DELETE oldRole
|
|
319
|
+
WITH DISTINCT b
|
|
320
|
+
MATCH (p:Profile {profileId: $profileId})
|
|
321
|
+
MERGE (b)-[created:CREATED_BY]->(p)
|
|
322
|
+
SET created.date = $date
|
|
323
|
+
MERGE (p)-[:HAS_ROLE {roleId: '__creator__'}]->(b)
|
|
324
|
+
WITH b
|
|
325
|
+
MATCH (b)-[:CREATED_BY]->(creator:Profile)
|
|
326
|
+
MATCH (roleOwner:Profile)-[:HAS_ROLE {roleId: '__creator__'}]->(b)
|
|
327
|
+
RETURN collect(creator.profileId) AS creatorProfileIds,
|
|
328
|
+
collect(roleOwner.profileId) AS roleOwnerProfileIds`,
|
|
329
|
+
{
|
|
330
|
+
boostId,
|
|
331
|
+
properties: boostProperties,
|
|
332
|
+
profileId,
|
|
333
|
+
date: new Date().toISOString(),
|
|
334
|
+
}
|
|
335
|
+
);
|
|
336
|
+
const creatorProfileIds = boostResult.records[0]?.get('creatorProfileIds');
|
|
337
|
+
const roleOwnerProfileIds = boostResult.records[0]?.get('roleOwnerProfileIds');
|
|
338
|
+
if (
|
|
339
|
+
creatorProfileIds?.length !== 1 ||
|
|
340
|
+
creatorProfileIds[0] !== profileId ||
|
|
341
|
+
roleOwnerProfileIds?.length !== 1 ||
|
|
342
|
+
roleOwnerProfileIds[0] !== profileId
|
|
343
|
+
) {
|
|
344
|
+
throw new Error(`Boost ${boostId} has ambiguous profile ownership.`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const contract = {
|
|
349
|
+
read: {
|
|
350
|
+
personal: { name: { required: false } },
|
|
351
|
+
credentials: { categories: { Achievement: { required: false } } },
|
|
352
|
+
},
|
|
353
|
+
write: {
|
|
354
|
+
personal: {},
|
|
355
|
+
credentials: {
|
|
356
|
+
categories: { Achievement: { required: false, defaultEnabled: true } },
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
const now = new Date().toISOString();
|
|
361
|
+
const contractProperties = flattenObject({
|
|
362
|
+
id: contractId,
|
|
363
|
+
name: `${bundle.displayName} Sample Credentials`,
|
|
364
|
+
subtitle: bundle.blurb,
|
|
365
|
+
description: bundle.blurb,
|
|
366
|
+
reasonForAccessing: '',
|
|
367
|
+
needsGuardianConsent: false,
|
|
368
|
+
redirectUrl: '',
|
|
369
|
+
frontDoorBoostUri: '',
|
|
370
|
+
image: '',
|
|
371
|
+
contract,
|
|
372
|
+
updatedAt: now,
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
await run(
|
|
376
|
+
`MERGE (c:ConsentFlowContract {id: $contractId})
|
|
377
|
+
ON CREATE SET c.createdAt = $createdAt
|
|
378
|
+
WITH c, c.createdAt AS createdAt
|
|
379
|
+
SET c = $properties,
|
|
380
|
+
c.createdAt = createdAt
|
|
381
|
+
WITH c
|
|
382
|
+
OPTIONAL MATCH (c)-[oldOwner:CREATED_BY]->(:Profile)
|
|
383
|
+
DELETE oldOwner
|
|
384
|
+
WITH DISTINCT c
|
|
385
|
+
MATCH (p:Profile {profileId: $profileId})
|
|
386
|
+
MERGE (c)-[:CREATED_BY]->(p)
|
|
387
|
+
RETURN c`,
|
|
388
|
+
{
|
|
389
|
+
contractId,
|
|
390
|
+
createdAt: now,
|
|
391
|
+
profileId: contractOwnerProfileId,
|
|
392
|
+
properties: contractProperties,
|
|
393
|
+
}
|
|
394
|
+
);
|
|
395
|
+
|
|
396
|
+
await run(
|
|
397
|
+
`MATCH (c:ConsentFlowContract {id: $contractId})
|
|
398
|
+
OPTIONAL MATCH (c)-[old:AUTO_RECEIVE]->(:Boost)
|
|
399
|
+
DELETE old
|
|
400
|
+
WITH DISTINCT c
|
|
401
|
+
UNWIND $autoBoosts AS autoBoost
|
|
402
|
+
MATCH (b:Boost {id: autoBoost.boostId})
|
|
403
|
+
CREATE (c)-[:AUTO_RECEIVE {
|
|
404
|
+
signingAuthorityEndpoint: $endpoint,
|
|
405
|
+
signingAuthorityName: $name,
|
|
406
|
+
issuer: autoBoost.issuerProfileId
|
|
407
|
+
}]->(b)`,
|
|
408
|
+
{
|
|
409
|
+
contractId,
|
|
410
|
+
autoBoosts,
|
|
411
|
+
endpoint: SIGNING_AUTHORITY_ENDPOINT,
|
|
412
|
+
name: SIGNING_AUTHORITY_NAME,
|
|
413
|
+
}
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
console.log(constructContractUri(contractId));
|
|
417
|
+
} finally {
|
|
418
|
+
await neogma.driver.close();
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
main().catch(error => {
|
|
423
|
+
console.error(error);
|
|
424
|
+
process.exitCode = 1;
|
|
425
|
+
});
|
package/serverless.yml
CHANGED
|
@@ -193,6 +193,25 @@ provider:
|
|
|
193
193
|
CREDENTIAL_REFRESH_ENABLED: ${env:CREDENTIAL_REFRESH_ENABLED, "false"}
|
|
194
194
|
CREDENTIAL_REFRESH_DIGEST_SECRET: ${env:CREDENTIAL_REFRESH_DIGEST_SECRET, ""}
|
|
195
195
|
CREDENTIAL_REFRESH_NOTIFICATION_WINDOW_HOURS: ${env:CREDENTIAL_REFRESH_NOTIFICATION_WINDOW_HOURS, "24"}
|
|
196
|
+
# Stable HMAC key for passcode-bearing share-link request fingerprints.
|
|
197
|
+
SHARE_LINK_REQUEST_HASH_SECRET: ${env:SHARE_LINK_REQUEST_HASH_SECRET, ""}
|
|
198
|
+
# LC-2187 share-link service wiring and automatic maintenance. Every value is
|
|
199
|
+
# bounded and re-validated fail-closed at runtime. Never read from the
|
|
200
|
+
# scheduled event payload.
|
|
201
|
+
SHARE_LINK_MAINTENANCE_NAMESPACE: ${env:SHARE_LINK_MAINTENANCE_NAMESPACE, ""}
|
|
202
|
+
SHARE_LINK_MAINTENANCE_ORIGIN: ${env:SHARE_LINK_MAINTENANCE_ORIGIN, ""}
|
|
203
|
+
SHARE_LINK_MAINTENANCE_AUDIENCE: ${env:SHARE_LINK_MAINTENANCE_AUDIENCE, ""}
|
|
204
|
+
SHARE_LINK_MAINTENANCE_ALLOW_INSECURE_LOOPBACK: ${env:SHARE_LINK_MAINTENANCE_ALLOW_INSECURE_LOOPBACK, "false"}
|
|
205
|
+
SHARE_LINK_MAINTENANCE_CLAIMANT: ${env:SHARE_LINK_MAINTENANCE_CLAIMANT, "brain-share-link-maintenance"}
|
|
206
|
+
SHARE_LINK_MAINTENANCE_RECOVERY_LIMIT: ${env:SHARE_LINK_MAINTENANCE_RECOVERY_LIMIT, "25"}
|
|
207
|
+
SHARE_LINK_MAINTENANCE_CLEANUP_LIMIT: ${env:SHARE_LINK_MAINTENANCE_CLEANUP_LIMIT, "25"}
|
|
208
|
+
SHARE_LINK_MAINTENANCE_LEASE_MS: ${env:SHARE_LINK_MAINTENANCE_LEASE_MS, "120000"}
|
|
209
|
+
SHARE_LINK_MAINTENANCE_CLAIM_MS: ${env:SHARE_LINK_MAINTENANCE_CLAIM_MS, "300000"}
|
|
210
|
+
SHARE_LINK_MAINTENANCE_BUDGET_MS: ${env:SHARE_LINK_MAINTENANCE_BUDGET_MS, "60000"}
|
|
211
|
+
SHARE_LINK_MAINTENANCE_INTERVAL_MS: ${env:SHARE_LINK_MAINTENANCE_INTERVAL_MS, "300000"}
|
|
212
|
+
SHARE_LINK_MAINTENANCE_REQUEST_TIMEOUT_MS: ${env:SHARE_LINK_MAINTENANCE_REQUEST_TIMEOUT_MS, "10000"}
|
|
213
|
+
SHARE_LINK_MAINTENANCE_FINALIZE_RESERVE_MS: ${env:SHARE_LINK_MAINTENANCE_FINALIZE_RESERVE_MS, "5000"}
|
|
214
|
+
SHARE_LINK_MAINTENANCE_GRAPH_TIMEOUT_MS: ${env:SHARE_LINK_MAINTENANCE_GRAPH_TIMEOUT_MS, "15000"}
|
|
196
215
|
tracing:
|
|
197
216
|
apiGateway: true
|
|
198
217
|
lambda: true
|
|
@@ -244,6 +263,23 @@ functions:
|
|
|
244
263
|
rate: rate(1 day)
|
|
245
264
|
enabled: true
|
|
246
265
|
|
|
266
|
+
# LC-2187 share-link recovery + cleanup. Dedicated entrypoint (no lambda.ts
|
|
267
|
+
# import-time work). Runs automatically with valid service configuration;
|
|
268
|
+
# absent wiring remains inert and partial wiring fails closed. The cadence
|
|
269
|
+
# matches the default Docker maintenance interval (5 minutes).
|
|
270
|
+
shareLinkMaintenance:
|
|
271
|
+
handler: shareLinkMaintenanceLambda.shareLinkMaintenanceHandler
|
|
272
|
+
timeout: 300
|
|
273
|
+
vpc:
|
|
274
|
+
securityGroupIds:
|
|
275
|
+
- 'Fn::GetAtt': [ServerlessSecurityGroup, GroupId]
|
|
276
|
+
subnetIds:
|
|
277
|
+
- Ref: PrivateSubnetA
|
|
278
|
+
events:
|
|
279
|
+
- schedule:
|
|
280
|
+
rate: rate(5 minutes)
|
|
281
|
+
enabled: true
|
|
282
|
+
|
|
247
283
|
trpc:
|
|
248
284
|
handler: lambda.trpcHandler
|
|
249
285
|
vpc:
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Context } from 'aws-lambda';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
createShareLinkMaintenanceRuntime,
|
|
5
|
+
type ShareLinkMaintenanceRuntime,
|
|
6
|
+
} from './src/helpers/share-link-maintenance';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Dedicated LC-2187 share-link maintenance Lambda entrypoint.
|
|
10
|
+
*
|
|
11
|
+
* It deliberately does NOT import `lambda.ts`, so no unrelated embedding
|
|
12
|
+
* backfill, tRPC router, Sentry input capture or inbox handler runs at import
|
|
13
|
+
* time. The only side effect is resolving the service and maintenance
|
|
14
|
+
* configuration; when it is absent or malformed the runtime is inert and the
|
|
15
|
+
* handler performs no graph, remote or signing work.
|
|
16
|
+
*
|
|
17
|
+
* The scheduled event payload is ignored entirely: it can never override the
|
|
18
|
+
* namespace, origin, audience or any other configuration, and it is never
|
|
19
|
+
* logged.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
let runtime: ShareLinkMaintenanceRuntime | null = null;
|
|
23
|
+
|
|
24
|
+
const getRuntime = (): ShareLinkMaintenanceRuntime => {
|
|
25
|
+
if (runtime === null) {
|
|
26
|
+
runtime = createShareLinkMaintenanceRuntime({
|
|
27
|
+
rawEnvironment: process.env as Record<string, unknown>,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return runtime;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const shareLinkMaintenanceHandler = async (
|
|
35
|
+
_event: unknown,
|
|
36
|
+
context?: Pick<Context, 'getRemainingTimeInMillis'>
|
|
37
|
+
): Promise<{ status: string }> => {
|
|
38
|
+
const hasRemainingTime = typeof context?.getRemainingTimeInMillis === 'function';
|
|
39
|
+
|
|
40
|
+
const summary = await getRuntime().runOnce({
|
|
41
|
+
// Preserve the LIVE Lambda remaining-time source: the runtime samples it
|
|
42
|
+
// once, before dependency initialization, and anchors the invocation
|
|
43
|
+
// budget to that instant.
|
|
44
|
+
remainingTimeMs: hasRemainingTime ? () => context!.getRemainingTimeInMillis() : undefined,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// The runtime already emitted one aggregate-only allowlisted event.
|
|
48
|
+
return { status: summary.status };
|
|
49
|
+
};
|