@mdbase-dev/sdk 0.0.0-stage → 0.1.0-beta.149
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/LICENSE +21 -0
- package/README.md +844 -2
- package/dist/account-key.d.ts +176 -0
- package/dist/account-key.js +409 -0
- package/dist/account-key.js.map +1 -0
- package/dist/account.d.ts +11 -0
- package/dist/account.js +9 -0
- package/dist/account.js.map +1 -0
- package/dist/app-grant/client.d.ts +209 -0
- package/dist/app-grant/client.js +930 -0
- package/dist/app-grant/client.js.map +1 -0
- package/dist/app-grant/grant-store.d.ts +77 -0
- package/dist/app-grant/grant-store.js +201 -0
- package/dist/app-grant/grant-store.js.map +1 -0
- package/dist/app-grant/index.d.ts +11 -0
- package/dist/app-grant/index.js +10 -0
- package/dist/app-grant/index.js.map +1 -0
- package/dist/app-grant/native-completion.d.ts +22 -0
- package/dist/app-grant/native-completion.js +63 -0
- package/dist/app-grant/native-completion.js.map +1 -0
- package/dist/app-grant/people.d.ts +10 -0
- package/dist/app-grant/people.js +84 -0
- package/dist/app-grant/people.js.map +1 -0
- package/dist/app-grant/setup-attempt.d.ts +12 -0
- package/dist/app-grant/setup-attempt.js +62 -0
- package/dist/app-grant/setup-attempt.js.map +1 -0
- package/dist/app-grant/setup-producer.d.ts +31 -0
- package/dist/app-grant/setup-producer.js +65 -0
- package/dist/app-grant/setup-producer.js.map +1 -0
- package/dist/app-grant/setup.d.ts +11 -0
- package/dist/app-grant/setup.js +222 -0
- package/dist/app-grant/setup.js.map +1 -0
- package/dist/app-host/app-environment.d.ts +27 -0
- package/dist/app-host/app-environment.js +48 -0
- package/dist/app-host/app-environment.js.map +1 -0
- package/dist/app-host/app-origin.d.ts +7 -0
- package/dist/app-host/app-origin.js +49 -0
- package/dist/app-host/app-origin.js.map +1 -0
- package/dist/app-host/bases-pages.d.ts +29 -0
- package/dist/app-host/bases-pages.js +42 -0
- package/dist/app-host/bases-pages.js.map +1 -0
- package/dist/app-host/bases-wire.d.ts +159 -0
- package/dist/app-host/bases-wire.js +376 -0
- package/dist/app-host/bases-wire.js.map +1 -0
- package/dist/app-host/browser-direct-access.d.ts +18 -0
- package/dist/app-host/browser-direct-access.js +17 -0
- package/dist/app-host/browser-direct-access.js.map +1 -0
- package/dist/app-host/cloud-copy-bootstrap.d.ts +127 -0
- package/dist/app-host/cloud-copy-bootstrap.js +608 -0
- package/dist/app-host/cloud-copy-bootstrap.js.map +1 -0
- package/dist/app-host/cloud-copy-host.d.ts +248 -0
- package/dist/app-host/cloud-copy-host.js +1028 -0
- package/dist/app-host/cloud-copy-host.js.map +1 -0
- package/dist/app-host/cloud-copy-persistence-idb.d.ts +33 -0
- package/dist/app-host/cloud-copy-persistence-idb.js +255 -0
- package/dist/app-host/cloud-copy-persistence-idb.js.map +1 -0
- package/dist/app-host/cloud-copy-persistence.d.ts +57 -0
- package/dist/app-host/cloud-copy-persistence.js +341 -0
- package/dist/app-host/cloud-copy-persistence.js.map +1 -0
- package/dist/app-host/collection-control.d.ts +111 -0
- package/dist/app-host/collection-control.js +604 -0
- package/dist/app-host/collection-control.js.map +1 -0
- package/dist/app-host/collection-delete.d.ts +7 -0
- package/dist/app-host/collection-delete.js +54 -0
- package/dist/app-host/collection-delete.js.map +1 -0
- package/dist/app-host/collection-display-name.d.ts +2 -0
- package/dist/app-host/collection-display-name.js +22 -0
- package/dist/app-host/collection-display-name.js.map +1 -0
- package/dist/app-host/collection-join-ledger.d.ts +52 -0
- package/dist/app-host/collection-join-ledger.js +208 -0
- package/dist/app-host/collection-join-ledger.js.map +1 -0
- package/dist/app-host/collection-people.d.ts +32 -0
- package/dist/app-host/collection-people.js +119 -0
- package/dist/app-host/collection-people.js.map +1 -0
- package/dist/app-host/collection-readiness.d.ts +119 -0
- package/dist/app-host/collection-readiness.js +649 -0
- package/dist/app-host/collection-readiness.js.map +1 -0
- package/dist/app-host/collection-setup-journal.d.ts +59 -0
- package/dist/app-host/collection-setup-journal.js +813 -0
- package/dist/app-host/collection-setup-journal.js.map +1 -0
- package/dist/app-host/collection-setup-types.d.ts +155 -0
- package/dist/app-host/collection-setup-types.js +10 -0
- package/dist/app-host/collection-setup-types.js.map +1 -0
- package/dist/app-host/cp-authority.d.ts +65 -0
- package/dist/app-host/cp-authority.js +243 -0
- package/dist/app-host/cp-authority.js.map +1 -0
- package/dist/app-host/cp-people.d.ts +23 -0
- package/dist/app-host/cp-people.js +145 -0
- package/dist/app-host/cp-people.js.map +1 -0
- package/dist/app-host/cp-problem.d.ts +34 -0
- package/dist/app-host/cp-problem.js +114 -0
- package/dist/app-host/cp-problem.js.map +1 -0
- package/dist/app-host/device-key-custody.d.ts +51 -0
- package/dist/app-host/device-key-custody.js +128 -0
- package/dist/app-host/device-key-custody.js.map +1 -0
- package/dist/app-host/device-key-idb.d.ts +31 -0
- package/dist/app-host/device-key-idb.js +176 -0
- package/dist/app-host/device-key-idb.js.map +1 -0
- package/dist/app-host/device-key-provider.d.ts +33 -0
- package/dist/app-host/device-key-provider.js +181 -0
- package/dist/app-host/device-key-provider.js.map +1 -0
- package/dist/app-host/device-registration.d.ts +51 -0
- package/dist/app-host/device-registration.js +180 -0
- package/dist/app-host/device-registration.js.map +1 -0
- package/dist/app-host/foreground-wake.d.ts +43 -0
- package/dist/app-host/foreground-wake.js +113 -0
- package/dist/app-host/foreground-wake.js.map +1 -0
- package/dist/app-host/handover.d.ts +27 -0
- package/dist/app-host/handover.js +82 -0
- package/dist/app-host/handover.js.map +1 -0
- package/dist/app-host/http-log.d.ts +96 -0
- package/dist/app-host/http-log.js +609 -0
- package/dist/app-host/http-log.js.map +1 -0
- package/dist/app-host/index.d.ts +63 -0
- package/dist/app-host/index.js +33 -0
- package/dist/app-host/index.js.map +1 -0
- package/dist/app-host/initial-sync.d.ts +22 -0
- package/dist/app-host/initial-sync.js +41 -0
- package/dist/app-host/initial-sync.js.map +1 -0
- package/dist/app-host/installation-sign-in.d.ts +319 -0
- package/dist/app-host/installation-sign-in.js +1231 -0
- package/dist/app-host/installation-sign-in.js.map +1 -0
- package/dist/app-host/installation-store.d.ts +56 -0
- package/dist/app-host/installation-store.js +285 -0
- package/dist/app-host/installation-store.js.map +1 -0
- package/dist/app-host/ledger-rows.d.ts +3 -0
- package/dist/app-host/ledger-rows.js +23 -0
- package/dist/app-host/ledger-rows.js.map +1 -0
- package/dist/app-host/local-facade.d.ts +24 -0
- package/dist/app-host/local-facade.js +361 -0
- package/dist/app-host/local-facade.js.map +1 -0
- package/dist/app-host/log-pump.d.ts +124 -0
- package/dist/app-host/log-pump.js +326 -0
- package/dist/app-host/log-pump.js.map +1 -0
- package/dist/app-host/log-push.d.ts +90 -0
- package/dist/app-host/log-push.js +377 -0
- package/dist/app-host/log-push.js.map +1 -0
- package/dist/app-host/log-token-cache.d.ts +28 -0
- package/dist/app-host/log-token-cache.js +104 -0
- package/dist/app-host/log-token-cache.js.map +1 -0
- package/dist/app-host/native-sign-in.d.ts +27 -0
- package/dist/app-host/native-sign-in.js +12 -0
- package/dist/app-host/native-sign-in.js.map +1 -0
- package/dist/app-host/noise-custody.d.ts +62 -0
- package/dist/app-host/noise-custody.js +238 -0
- package/dist/app-host/noise-custody.js.map +1 -0
- package/dist/app-host/noise-idb.d.ts +33 -0
- package/dist/app-host/noise-idb.js +199 -0
- package/dist/app-host/noise-idb.js.map +1 -0
- package/dist/app-host/open-wait.d.ts +3 -0
- package/dist/app-host/open-wait.js +17 -0
- package/dist/app-host/open-wait.js.map +1 -0
- package/dist/app-host/opening-progress.d.ts +3 -0
- package/dist/app-host/opening-progress.js +5 -0
- package/dist/app-host/opening-progress.js.map +1 -0
- package/dist/app-host/owner.d.ts +103 -0
- package/dist/app-host/owner.js +262 -0
- package/dist/app-host/owner.js.map +1 -0
- package/dist/app-host/private-bootstrap.d.ts +78 -0
- package/dist/app-host/private-bootstrap.js +230 -0
- package/dist/app-host/private-bootstrap.js.map +1 -0
- package/dist/app-host/private-persistence-idb.d.ts +32 -0
- package/dist/app-host/private-persistence-idb.js +188 -0
- package/dist/app-host/private-persistence-idb.js.map +1 -0
- package/dist/app-host/private-persistence.d.ts +55 -0
- package/dist/app-host/private-persistence.js +257 -0
- package/dist/app-host/private-persistence.js.map +1 -0
- package/dist/app-host/scoped-sign-in-session.d.ts +49 -0
- package/dist/app-host/scoped-sign-in-session.js +243 -0
- package/dist/app-host/scoped-sign-in-session.js.map +1 -0
- package/dist/app-host/setup-engine.d.ts +14 -0
- package/dist/app-host/setup-engine.js +73 -0
- package/dist/app-host/setup-engine.js.map +1 -0
- package/dist/app-host/sign-out-erase.d.ts +37 -0
- package/dist/app-host/sign-out-erase.js +139 -0
- package/dist/app-host/sign-out-erase.js.map +1 -0
- package/dist/app-host/status.d.ts +62 -0
- package/dist/app-host/status.js +43 -0
- package/dist/app-host/status.js.map +1 -0
- package/dist/app-host/storage-probe.d.ts +46 -0
- package/dist/app-host/storage-probe.js +63 -0
- package/dist/app-host/storage-probe.js.map +1 -0
- package/dist/app-host/timer-port.d.ts +29 -0
- package/dist/app-host/timer-port.js +483 -0
- package/dist/app-host/timer-port.js.map +1 -0
- package/dist/app-host/wasm-runtime.d.ts +302 -0
- package/dist/app-host/wasm-runtime.js +1050 -0
- package/dist/app-host/wasm-runtime.js.map +1 -0
- package/dist/app-host/web-collection.d.ts +78 -0
- package/dist/app-host/web-collection.js +671 -0
- package/dist/app-host/web-collection.js.map +1 -0
- package/dist/app-host/web-sign-in-problem.d.ts +17 -0
- package/dist/app-host/web-sign-in-problem.js +59 -0
- package/dist/app-host/web-sign-in-problem.js.map +1 -0
- package/dist/app-host/web-sign-in-session.d.ts +367 -0
- package/dist/app-host/web-sign-in-session.js +1258 -0
- package/dist/app-host/web-sign-in-session.js.map +1 -0
- package/dist/app-storage/app-binary-index.d.ts +33 -0
- package/dist/app-storage/app-binary-index.js +274 -0
- package/dist/app-storage/app-binary-index.js.map +1 -0
- package/dist/app-storage/app-sqlite-index.d.ts +40 -0
- package/dist/app-storage/app-sqlite-index.js +102 -0
- package/dist/app-storage/app-sqlite-index.js.map +1 -0
- package/dist/app-storage/collection-sql.d.ts +39 -0
- package/dist/app-storage/collection-sql.js +93 -0
- package/dist/app-storage/collection-sql.js.map +1 -0
- package/dist/app-storage/index.d.ts +10 -0
- package/dist/app-storage/index.js +7 -0
- package/dist/app-storage/index.js.map +1 -0
- package/dist/app-storage/sqlite-index.d.ts +95 -0
- package/dist/app-storage/sqlite-index.js +280 -0
- package/dist/app-storage/sqlite-index.js.map +1 -0
- package/dist/application/asset-loader.d.ts +22 -0
- package/dist/application/asset-loader.js +130 -0
- package/dist/application/asset-loader.js.map +1 -0
- package/dist/application/asset-pins.json +24 -0
- package/dist/application/browser-capabilities.d.ts +48 -0
- package/dist/application/browser-capabilities.js +87 -0
- package/dist/application/browser-capabilities.js.map +1 -0
- package/dist/application/browser-selection.d.ts +58 -0
- package/dist/application/browser-selection.js +160 -0
- package/dist/application/browser-selection.js.map +1 -0
- package/dist/application/capabilities.d.ts +20 -0
- package/dist/application/capabilities.js +22 -0
- package/dist/application/capabilities.js.map +1 -0
- package/dist/application/collection-selection.d.ts +147 -0
- package/dist/application/collection-selection.js +351 -0
- package/dist/application/collection-selection.js.map +1 -0
- package/dist/application/configuration.d.ts +52 -0
- package/dist/application/configuration.js +568 -0
- package/dist/application/configuration.js.map +1 -0
- package/dist/application/declaration.d.ts +51 -0
- package/dist/application/declaration.js +100 -0
- package/dist/application/declaration.js.map +1 -0
- package/dist/application/entry.d.ts +343 -0
- package/dist/application/entry.js +945 -0
- package/dist/application/entry.js.map +1 -0
- package/dist/application/file-access.d.ts +55 -0
- package/dist/application/file-access.js +93 -0
- package/dist/application/file-access.js.map +1 -0
- package/dist/application/file-readiness.d.ts +16 -0
- package/dist/application/file-readiness.js +53 -0
- package/dist/application/file-readiness.js.map +1 -0
- package/dist/application/forgotten.d.ts +15 -0
- package/dist/application/forgotten.js +70 -0
- package/dist/application/forgotten.js.map +1 -0
- package/dist/application/front-door.d.ts +68 -0
- package/dist/application/front-door.js +66 -0
- package/dist/application/front-door.js.map +1 -0
- package/dist/application/local-build.d.ts +5 -0
- package/dist/application/local-build.js +22 -0
- package/dist/application/local-build.js.map +1 -0
- package/dist/application/manifest.d.ts +16 -0
- package/dist/application/manifest.js +31 -0
- package/dist/application/manifest.js.map +1 -0
- package/dist/application/native-assets.d.ts +25 -0
- package/dist/application/native-assets.js +29 -0
- package/dist/application/native-assets.js.map +1 -0
- package/dist/application/native-authorization-rpc.d.ts +23 -0
- package/dist/application/native-authorization-rpc.js +54 -0
- package/dist/application/native-authorization-rpc.js.map +1 -0
- package/dist/application/notification-readiness.d.ts +33 -0
- package/dist/application/notification-readiness.js +222 -0
- package/dist/application/notification-readiness.js.map +1 -0
- package/dist/application/packaged-assets.d.ts +5 -0
- package/dist/application/packaged-assets.js +55 -0
- package/dist/application/packaged-assets.js.map +1 -0
- package/dist/application/packaged-trust.d.ts +5 -0
- package/dist/application/packaged-trust.js +10 -0
- package/dist/application/packaged-trust.js.map +1 -0
- package/dist/application/people-readiness.d.ts +23 -0
- package/dist/application/people-readiness.js +213 -0
- package/dist/application/people-readiness.js.map +1 -0
- package/dist/application/phase.d.ts +108 -0
- package/dist/application/phase.js +113 -0
- package/dist/application/phase.js.map +1 -0
- package/dist/application/portal-reservation.d.ts +38 -0
- package/dist/application/portal-reservation.js +183 -0
- package/dist/application/portal-reservation.js.map +1 -0
- package/dist/application/private-collections.d.ts +114 -0
- package/dist/application/private-collections.js +415 -0
- package/dist/application/private-collections.js.map +1 -0
- package/dist/application/readiness.d.ts +59 -0
- package/dist/application/readiness.js +223 -0
- package/dist/application/readiness.js.map +1 -0
- package/dist/application/registration-refusal.d.ts +16 -0
- package/dist/application/registration-refusal.js +41 -0
- package/dist/application/registration-refusal.js.map +1 -0
- package/dist/application/registration.d.ts +26 -0
- package/dist/application/registration.js +372 -0
- package/dist/application/registration.js.map +1 -0
- package/dist/application/return-url.d.ts +1 -0
- package/dist/application/return-url.js +41 -0
- package/dist/application/return-url.js.map +1 -0
- package/dist/application/runtime.d.ts +107 -0
- package/dist/application/runtime.js +379 -0
- package/dist/application/runtime.js.map +1 -0
- package/dist/application/scope.d.ts +34 -0
- package/dist/application/scope.js +164 -0
- package/dist/application/scope.js.map +1 -0
- package/dist/application/session-hint.d.ts +21 -0
- package/dist/application/session-hint.js +87 -0
- package/dist/application/session-hint.js.map +1 -0
- package/dist/application/setup.d.ts +105 -0
- package/dist/application/setup.js +137 -0
- package/dist/application/setup.js.map +1 -0
- package/dist/application/sign-out.d.ts +17 -0
- package/dist/application/sign-out.js +28 -0
- package/dist/application/sign-out.js.map +1 -0
- package/dist/application/storage-scope.d.ts +8 -0
- package/dist/application/storage-scope.js +15 -0
- package/dist/application/storage-scope.js.map +1 -0
- package/dist/application/tabs.d.ts +98 -0
- package/dist/application/tabs.js +407 -0
- package/dist/application/tabs.js.map +1 -0
- package/dist/application/timer-criteria.d.ts +5 -0
- package/dist/application/timer-criteria.js +15 -0
- package/dist/application/timer-criteria.js.map +1 -0
- package/dist/application/ui-connections.d.ts +35 -0
- package/dist/application/ui-connections.js +129 -0
- package/dist/application/ui-connections.js.map +1 -0
- package/dist/application/worker-client.d.ts +59 -0
- package/dist/application/worker-client.js +381 -0
- package/dist/application/worker-client.js.map +1 -0
- package/dist/application/worker-host.d.ts +84 -0
- package/dist/application/worker-host.js +547 -0
- package/dist/application/worker-host.js.map +1 -0
- package/dist/application/worker-protocol.d.ts +40 -0
- package/dist/application/worker-protocol.js +83 -0
- package/dist/application/worker-protocol.js.map +1 -0
- package/dist/application/worker-session.d.ts +45 -0
- package/dist/application/worker-session.js +37 -0
- package/dist/application/worker-session.js.map +1 -0
- package/dist/application/worker.d.ts +1 -0
- package/dist/application/worker.js +34826 -0
- package/dist/application/worker.js.map +1 -0
- package/dist/attachment-wire.d.ts +15 -0
- package/dist/attachment-wire.js +47 -0
- package/dist/attachment-wire.js.map +1 -0
- package/dist/browser/mdbase-sdk.js +49392 -0
- package/dist/browser/mdbase-sdk.min.js +130 -0
- package/dist/browser.d.ts +4 -0
- package/dist/browser.js +5 -0
- package/dist/browser.js.map +1 -0
- package/dist/cbor.d.ts +52 -0
- package/dist/cbor.js +480 -0
- package/dist/cbor.js.map +1 -0
- package/dist/client.d.ts +656 -0
- package/dist/client.js +1962 -0
- package/dist/client.js.map +1 -0
- package/dist/codec.d.ts +82 -0
- package/dist/codec.js +388 -0
- package/dist/codec.js.map +1 -0
- package/dist/collection-availability.d.ts +34 -0
- package/dist/collection-availability.js +63 -0
- package/dist/collection-availability.js.map +1 -0
- package/dist/contract-query.d.ts +31 -0
- package/dist/contract-query.js +13 -0
- package/dist/contract-query.js.map +1 -0
- package/dist/contract-records.d.ts +51 -0
- package/dist/contract-records.js +14 -0
- package/dist/contract-records.js.map +1 -0
- package/dist/describe-error.d.ts +61 -0
- package/dist/describe-error.js +452 -0
- package/dist/describe-error.js.map +1 -0
- package/dist/errors.d.ts +65 -0
- package/dist/errors.js +94 -0
- package/dist/errors.js.map +1 -0
- package/dist/files.d.ts +147 -0
- package/dist/files.js +537 -0
- package/dist/files.js.map +1 -0
- package/dist/holds.d.ts +74 -0
- package/dist/holds.js +118 -0
- package/dist/holds.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/keys.d.ts +40 -0
- package/dist/keys.js +181 -0
- package/dist/keys.js.map +1 -0
- package/dist/live.d.ts +38 -0
- package/dist/live.js +82 -0
- package/dist/live.js.map +1 -0
- package/dist/local-build.d.ts +9 -0
- package/dist/local-build.js +33 -0
- package/dist/local-build.js.map +1 -0
- package/dist/native/provenance.json +23 -0
- package/dist/native/runtime.wasm +0 -0
- package/dist/native/sqlite3.d.ts +5 -0
- package/dist/native/sqlite3.js +17392 -0
- package/dist/native/sqlite3.js.map +1 -0
- package/dist/native/sqlite3.wasm +0 -0
- package/dist/node.d.ts +63 -0
- package/dist/node.js +255 -0
- package/dist/node.js.map +1 -0
- package/dist/notifications.d.ts +95 -0
- package/dist/notifications.js +226 -0
- package/dist/notifications.js.map +1 -0
- package/dist/offline-shell-build.d.ts +25 -0
- package/dist/offline-shell-build.js +78 -0
- package/dist/offline-shell-build.js.map +1 -0
- package/dist/offline-shell-worker.d.ts +46 -0
- package/dist/offline-shell-worker.js +115 -0
- package/dist/offline-shell-worker.js.map +1 -0
- package/dist/people.d.ts +82 -0
- package/dist/people.js +199 -0
- package/dist/people.js.map +1 -0
- package/dist/presence.d.ts +21 -0
- package/dist/presence.js +109 -0
- package/dist/presence.js.map +1 -0
- package/dist/private-account.d.ts +197 -0
- package/dist/private-account.js +510 -0
- package/dist/private-account.js.map +1 -0
- package/dist/private.d.ts +55 -0
- package/dist/private.js +69 -0
- package/dist/private.js.map +1 -0
- package/dist/read-helpers.d.ts +32 -0
- package/dist/read-helpers.js +181 -0
- package/dist/read-helpers.js.map +1 -0
- package/dist/records/session.d.ts +60 -0
- package/dist/records/session.js +534 -0
- package/dist/records/session.js.map +1 -0
- package/dist/records/types.d.ts +76 -0
- package/dist/records/types.js +2 -0
- package/dist/records/types.js.map +1 -0
- package/dist/records/witness.d.ts +19 -0
- package/dist/records/witness.js +64 -0
- package/dist/records/witness.js.map +1 -0
- package/dist/records.d.ts +23 -0
- package/dist/records.js +234 -0
- package/dist/records.js.map +1 -0
- package/dist/runtime/wasm.d.ts +69 -0
- package/dist/runtime/wasm.js +274 -0
- package/dist/runtime/wasm.js.map +1 -0
- package/dist/runtime-wire.d.ts +71 -0
- package/dist/runtime-wire.js +71 -0
- package/dist/runtime-wire.js.map +1 -0
- package/dist/saved-views.d.ts +29 -0
- package/dist/saved-views.js +171 -0
- package/dist/saved-views.js.map +1 -0
- package/dist/semver.d.ts +22 -0
- package/dist/semver.js +63 -0
- package/dist/semver.js.map +1 -0
- package/dist/session.d.ts +65 -0
- package/dist/session.js +332 -0
- package/dist/session.js.map +1 -0
- package/dist/status.d.ts +46 -0
- package/dist/status.js +59 -0
- package/dist/status.js.map +1 -0
- package/dist/strength.d.ts +12 -0
- package/dist/strength.js +194 -0
- package/dist/strength.js.map +1 -0
- package/dist/testing/application.d.ts +59 -0
- package/dist/testing/application.js +230 -0
- package/dist/testing/application.js.map +1 -0
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/index.js +6 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/memory-contracts.d.ts +40 -0
- package/dist/testing/memory-contracts.js +127 -0
- package/dist/testing/memory-contracts.js.map +1 -0
- package/dist/testing/memory-replica.d.ts +191 -0
- package/dist/testing/memory-replica.js +1465 -0
- package/dist/testing/memory-replica.js.map +1 -0
- package/dist/testing/noise-server.d.ts +11 -0
- package/dist/testing/noise-server.js +65 -0
- package/dist/testing/noise-server.js.map +1 -0
- package/dist/testing/test-app.d.ts +93 -0
- package/dist/testing/test-app.js +140 -0
- package/dist/testing/test-app.js.map +1 -0
- package/dist/thin-client.d.ts +67 -0
- package/dist/thin-client.js +42 -0
- package/dist/thin-client.js.map +1 -0
- package/dist/timers.d.ts +158 -0
- package/dist/timers.js +258 -0
- package/dist/timers.js.map +1 -0
- package/dist/transport/bases-rpc.d.ts +15 -0
- package/dist/transport/bases-rpc.js +61 -0
- package/dist/transport/bases-rpc.js.map +1 -0
- package/dist/transport/control-route.d.ts +34 -0
- package/dist/transport/control-route.js +84 -0
- package/dist/transport/control-route.js.map +1 -0
- package/dist/transport/inprocess.d.ts +13 -0
- package/dist/transport/inprocess.js +37 -0
- package/dist/transport/inprocess.js.map +1 -0
- package/dist/transport/local-link.d.ts +53 -0
- package/dist/transport/local-link.js +66 -0
- package/dist/transport/local-link.js.map +1 -0
- package/dist/transport/next-relay.d.ts +64 -0
- package/dist/transport/next-relay.js +222 -0
- package/dist/transport/next-relay.js.map +1 -0
- package/dist/transport/noise-session.d.ts +88 -0
- package/dist/transport/noise-session.js +264 -0
- package/dist/transport/noise-session.js.map +1 -0
- package/dist/transport/noise.d.ts +102 -0
- package/dist/transport/noise.js +307 -0
- package/dist/transport/noise.js.map +1 -0
- package/dist/transport/original-session.d.ts +6 -0
- package/dist/transport/original-session.js +6 -0
- package/dist/transport/original-session.js.map +1 -0
- package/dist/transport/port.d.ts +67 -0
- package/dist/transport/port.js +184 -0
- package/dist/transport/port.js.map +1 -0
- package/dist/transport/read-fence-policy.d.ts +3 -0
- package/dist/transport/read-fence-policy.js +11 -0
- package/dist/transport/read-fence-policy.js.map +1 -0
- package/dist/transport/relay-close.d.ts +31 -0
- package/dist/transport/relay-close.js +23 -0
- package/dist/transport/relay-close.js.map +1 -0
- package/dist/transport/relay-pipe.d.ts +15 -0
- package/dist/transport/relay-pipe.js +190 -0
- package/dist/transport/relay-pipe.js.map +1 -0
- package/dist/transport/relay.d.ts +36 -0
- package/dist/transport/relay.js +45 -0
- package/dist/transport/relay.js.map +1 -0
- package/dist/type-packs.d.ts +124 -0
- package/dist/type-packs.js +188 -0
- package/dist/type-packs.js.map +1 -0
- package/dist/validation.d.ts +30 -0
- package/dist/validation.js +125 -0
- package/dist/validation.js.map +1 -0
- package/dist/values.d.ts +37 -0
- package/dist/values.js +133 -0
- package/dist/values.js.map +1 -0
- package/dist/view-sources.d.ts +31 -0
- package/dist/view-sources.js +78 -0
- package/dist/view-sources.js.map +1 -0
- package/dist/wire.d.ts +856 -0
- package/dist/wire.js +914 -0
- package/dist/wire.js.map +1 -0
- package/dist/witness.d.ts +7 -0
- package/dist/witness.js +82 -0
- package/dist/witness.js.map +1 -0
- package/dist/write-ledger.d.ts +41 -0
- package/dist/write-ledger.js +184 -0
- package/dist/write-ledger.js.map +1 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/application-authorization.d.ts +32 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/application-authorization.js +207 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/application-contract.d.ts +23 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/application-contract.js +76 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/application-declaration.d.ts +120 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/application-declaration.js +1 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/authorization-errors.d.ts +34 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/authorization-errors.js +52 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/capabilities.d.ts +73 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/capabilities.js +92 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/change-events.generated.d.ts +48 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/change-events.generated.js +18 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/collection-setup.d.ts +93 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/collection-setup.js +7 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/compatibility.d.ts +37 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/compatibility.js +65 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/connect-problems.generated.d.ts +1533 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/connect-problems.generated.js +598 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/files.d.ts +288 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/files.js +426 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/index.d.ts +723 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/index.js +104 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/manifest-validators.generated.d.ts +13 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/manifest-validators.generated.js +7940 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/manifest.d.ts +72 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/manifest.js +643 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/mutation-fingerprint.d.ts +6 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/mutation-fingerprint.js +116 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/next-authorization.d.ts +30 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/next-authorization.js +90 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/operations.d.ts +15 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/operations.js +196 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/people.d.ts +33 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/people.js +26 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/records.d.ts +108 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/records.js +3 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/type-packs.d.ts +154 -0
- package/node_modules/@mdbase-dev/connect-protocol/dist/type-packs.js +30 -0
- package/node_modules/@mdbase-dev/connect-protocol/package.json +49 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/application-capability-catalog.v1.json +40 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/application-capability-catalog.v2.json +68 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/catalog.json +17 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/change-events.v1.json +48 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/connect-problem.v1.schema.json +5665 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/connect-problems.v1.catalog.json +373 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/connect-protocol.v1.schema.json +901 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/data-contract.schema.json +163 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/encrypted-relay.v1.schema.json +63 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/encrypted-relay.v2.schema.json +63 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/encrypted-relay.v3.schema.json +64 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/files.v1.schema.json +551 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/interop/v0.1/action-cancellation.schema.json +6 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/interop/v0.1/action-invocation.schema.json +6 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/interop/v0.1/action-outcome.schema.json +6 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/interop/v0.1/action-provider-declaration.schema.json +6 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/interop/v0.1/action-request.schema.json +6 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/interop/v0.1/conformance-claim.schema.json +6 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/interop/v0.1/event-source-declaration.schema.json +6 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/interop/v0.1/event.schema.json +6 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/interop/v0.1/profile.schema.json +456 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/mdbase-app.legacy-v1.schema.json +430 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/mdbase-app.schema.json +437 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/mdbase-query.v0.3.schema.json +176 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/next-trust.v1.schema.json +54 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/notification-webhook.v1.schema.json +56 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/operation-catalog.v1.json +43 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/operation-mutation-classification.v1.json +554 -0
- package/node_modules/@mdbase-dev/connect-protocol/schemas/sync.v1.schema.json +483 -0
- package/node_modules/@noble/hashes/LICENSE +21 -0
- package/node_modules/@noble/hashes/README.md +478 -0
- package/node_modules/@noble/hashes/_blake.d.ts +20 -0
- package/node_modules/@noble/hashes/_blake.js +59 -0
- package/node_modules/@noble/hashes/_md.d.ts +95 -0
- package/node_modules/@noble/hashes/_md.js +209 -0
- package/node_modules/@noble/hashes/_u64.d.ts +36 -0
- package/node_modules/@noble/hashes/_u64.js +77 -0
- package/node_modules/@noble/hashes/argon2.d.ts +148 -0
- package/node_modules/@noble/hashes/argon2.js +577 -0
- package/node_modules/@noble/hashes/blake1.d.ts +162 -0
- package/node_modules/@noble/hashes/blake1.js +630 -0
- package/node_modules/@noble/hashes/blake2.d.ts +203 -0
- package/node_modules/@noble/hashes/blake2.js +573 -0
- package/node_modules/@noble/hashes/blake3.d.ts +68 -0
- package/node_modules/@noble/hashes/blake3.js +310 -0
- package/node_modules/@noble/hashes/eskdf.d.ts +91 -0
- package/node_modules/@noble/hashes/eskdf.js +225 -0
- package/node_modules/@noble/hashes/hkdf.d.ts +70 -0
- package/node_modules/@noble/hashes/hkdf.js +152 -0
- package/node_modules/@noble/hashes/hmac.d.ts +50 -0
- package/node_modules/@noble/hashes/hmac.js +93 -0
- package/node_modules/@noble/hashes/index.d.ts +1 -0
- package/node_modules/@noble/hashes/index.js +34 -0
- package/node_modules/@noble/hashes/legacy.d.ts +107 -0
- package/node_modules/@noble/hashes/legacy.js +348 -0
- package/node_modules/@noble/hashes/package.json +91 -0
- package/node_modules/@noble/hashes/pbkdf2.d.ts +66 -0
- package/node_modules/@noble/hashes/pbkdf2.js +176 -0
- package/node_modules/@noble/hashes/scrypt.d.ts +98 -0
- package/node_modules/@noble/hashes/scrypt.js +304 -0
- package/node_modules/@noble/hashes/sha2.d.ts +176 -0
- package/node_modules/@noble/hashes/sha2.js +446 -0
- package/node_modules/@noble/hashes/sha3-addons.d.ts +533 -0
- package/node_modules/@noble/hashes/sha3-addons.js +973 -0
- package/node_modules/@noble/hashes/sha3.d.ts +208 -0
- package/node_modules/@noble/hashes/sha3.js +475 -0
- package/node_modules/@noble/hashes/src/_blake.ts +67 -0
- package/node_modules/@noble/hashes/src/_md.ts +227 -0
- package/node_modules/@noble/hashes/src/_u64.ts +111 -0
- package/node_modules/@noble/hashes/src/argon2.ts +693 -0
- package/node_modules/@noble/hashes/src/blake1.ts +677 -0
- package/node_modules/@noble/hashes/src/blake2.ts +648 -0
- package/node_modules/@noble/hashes/src/blake3.ts +344 -0
- package/node_modules/@noble/hashes/src/eskdf.ts +265 -0
- package/node_modules/@noble/hashes/src/hkdf.ts +161 -0
- package/node_modules/@noble/hashes/src/hmac.ts +130 -0
- package/node_modules/@noble/hashes/src/index.ts +33 -0
- package/node_modules/@noble/hashes/src/legacy.ts +361 -0
- package/node_modules/@noble/hashes/src/pbkdf2.ts +219 -0
- package/node_modules/@noble/hashes/src/scrypt.ts +375 -0
- package/node_modules/@noble/hashes/src/sha2.ts +486 -0
- package/node_modules/@noble/hashes/src/sha3-addons.ts +1157 -0
- package/node_modules/@noble/hashes/src/sha3.ts +525 -0
- package/node_modules/@noble/hashes/src/utils.ts +978 -0
- package/node_modules/@noble/hashes/src/webcrypto.ts +283 -0
- package/node_modules/@noble/hashes/utils.d.ts +560 -0
- package/node_modules/@noble/hashes/utils.js +687 -0
- package/node_modules/@noble/hashes/webcrypto.d.ts +121 -0
- package/node_modules/@noble/hashes/webcrypto.js +228 -0
- package/node_modules/yaml/LICENSE +13 -0
- package/node_modules/yaml/README.md +172 -0
- package/node_modules/yaml/bin.mjs +11 -0
- package/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
- package/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
- package/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
- package/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
- package/node_modules/yaml/browser/dist/compose/composer.js +219 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
- package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
- package/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
- package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
- package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +226 -0
- package/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
- package/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
- package/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
- package/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
- package/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
- package/node_modules/yaml/browser/dist/doc/Document.js +335 -0
- package/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
- package/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
- package/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
- package/node_modules/yaml/browser/dist/doc/directives.js +176 -0
- package/node_modules/yaml/browser/dist/errors.js +57 -0
- package/node_modules/yaml/browser/dist/index.js +17 -0
- package/node_modules/yaml/browser/dist/log.js +11 -0
- package/node_modules/yaml/browser/dist/nodes/Alias.js +118 -0
- package/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
- package/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
- package/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
- package/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
- package/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
- package/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
- package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
- package/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
- package/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
- package/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
- package/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
- package/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
- package/node_modules/yaml/browser/dist/parse/cst.js +98 -0
- package/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
- package/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
- package/node_modules/yaml/browser/dist/parse/parser.js +975 -0
- package/node_modules/yaml/browser/dist/public-api.js +102 -0
- package/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
- package/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
- package/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
- package/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
- package/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
- package/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
- package/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
- package/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
- package/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
- package/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
- package/node_modules/yaml/browser/dist/schema/tags.js +96 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
- package/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
- package/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
- package/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
- package/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
- package/node_modules/yaml/browser/dist/util.js +11 -0
- package/node_modules/yaml/browser/dist/visit.js +233 -0
- package/node_modules/yaml/browser/index.js +5 -0
- package/node_modules/yaml/browser/package.json +3 -0
- package/node_modules/yaml/dist/cli.d.ts +8 -0
- package/node_modules/yaml/dist/cli.mjs +201 -0
- package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
- package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
- package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
- package/node_modules/yaml/dist/compose/compose-doc.js +45 -0
- package/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
- package/node_modules/yaml/dist/compose/compose-node.js +112 -0
- package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
- package/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
- package/node_modules/yaml/dist/compose/composer.d.ts +63 -0
- package/node_modules/yaml/dist/compose/composer.js +224 -0
- package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
- package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
- package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
- package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
- package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
- package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
- package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
- package/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
- package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
- package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +228 -0
- package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
- package/node_modules/yaml/dist/compose/resolve-props.js +148 -0
- package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
- package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
- package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
- package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
- package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
- package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
- package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
- package/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
- package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
- package/node_modules/yaml/dist/doc/Document.js +337 -0
- package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
- package/node_modules/yaml/dist/doc/anchors.js +76 -0
- package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
- package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
- package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
- package/node_modules/yaml/dist/doc/createNode.js +90 -0
- package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
- package/node_modules/yaml/dist/doc/directives.js +178 -0
- package/node_modules/yaml/dist/errors.d.ts +21 -0
- package/node_modules/yaml/dist/errors.js +62 -0
- package/node_modules/yaml/dist/index.d.ts +25 -0
- package/node_modules/yaml/dist/index.js +50 -0
- package/node_modules/yaml/dist/log.d.ts +3 -0
- package/node_modules/yaml/dist/log.js +19 -0
- package/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
- package/node_modules/yaml/dist/nodes/Alias.js +120 -0
- package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
- package/node_modules/yaml/dist/nodes/Collection.js +151 -0
- package/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
- package/node_modules/yaml/dist/nodes/Node.js +40 -0
- package/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
- package/node_modules/yaml/dist/nodes/Pair.js +39 -0
- package/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
- package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
- package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
- package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
- package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
- package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
- package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
- package/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
- package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
- package/node_modules/yaml/dist/nodes/identity.js +53 -0
- package/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
- package/node_modules/yaml/dist/nodes/toJS.js +39 -0
- package/node_modules/yaml/dist/options.d.ts +350 -0
- package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
- package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
- package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
- package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
- package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
- package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
- package/node_modules/yaml/dist/parse/cst.d.ts +109 -0
- package/node_modules/yaml/dist/parse/cst.js +112 -0
- package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
- package/node_modules/yaml/dist/parse/lexer.js +723 -0
- package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
- package/node_modules/yaml/dist/parse/line-counter.js +41 -0
- package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
- package/node_modules/yaml/dist/parse/parser.js +980 -0
- package/node_modules/yaml/dist/public-api.d.ts +44 -0
- package/node_modules/yaml/dist/public-api.js +107 -0
- package/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
- package/node_modules/yaml/dist/schema/Schema.js +39 -0
- package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/map.js +19 -0
- package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
- package/node_modules/yaml/dist/schema/common/null.js +17 -0
- package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/seq.js +19 -0
- package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
- package/node_modules/yaml/dist/schema/common/string.js +16 -0
- package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/bool.js +21 -0
- package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/float.js +47 -0
- package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
- package/node_modules/yaml/dist/schema/core/int.js +42 -0
- package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
- package/node_modules/yaml/dist/schema/core/schema.js +25 -0
- package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
- package/node_modules/yaml/dist/schema/json/schema.js +64 -0
- package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
- package/node_modules/yaml/dist/schema/tags.d.ts +48 -0
- package/node_modules/yaml/dist/schema/tags.js +99 -0
- package/node_modules/yaml/dist/schema/types.d.ts +92 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
- package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
- package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
- package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
- package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
- package/node_modules/yaml/dist/stringify/stringify.js +132 -0
- package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
- package/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
- package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
- package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
- package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
- package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
- package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
- package/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
- package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
- package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
- package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
- package/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
- package/node_modules/yaml/dist/test-events.d.ts +4 -0
- package/node_modules/yaml/dist/test-events.js +134 -0
- package/node_modules/yaml/dist/util.d.ts +16 -0
- package/node_modules/yaml/dist/util.js +28 -0
- package/node_modules/yaml/dist/visit.d.ts +102 -0
- package/node_modules/yaml/dist/visit.js +236 -0
- package/node_modules/yaml/package.json +97 -0
- package/node_modules/yaml/util.js +2 -0
- package/package.json +108 -4
- package/vendor/mdbase-connect-sdk-e6e66bcd172f.json +13 -0
- package/vendor/mdbase-dev-connect-protocol-0.1.0-beta.145-e6e66bcd172f.tgz +0 -0
|
@@ -0,0 +1,1258 @@
|
|
|
1
|
+
import { appServerOutcome, isAppServerProblem, sanitizeAppServerProblem, MIN_SERVER_RETRY_MS, MAX_SERVER_RETRY_MS } from "./cp-problem.js";
|
|
2
|
+
import { AppProtectedInstallationSignIn, AppInstallationSignInError } from "./installation-sign-in.js";
|
|
3
|
+
import { AppWebCloudCopyHost } from "./cloud-copy-host.js";
|
|
4
|
+
import { AppCollectionDeleteError, collectionDeleteError } from "./collection-delete.js";
|
|
5
|
+
import { webSignInProblem } from "./web-sign-in-problem.js";
|
|
6
|
+
import { appBrowserDirectAccess } from "./browser-direct-access.js";
|
|
7
|
+
import { AppCloudCopyBootstrapError } from "./cloud-copy-bootstrap.js";
|
|
8
|
+
import { selectAppEnvironment } from "./app-environment.js";
|
|
9
|
+
import { acquireAppInstallationLease, acquireAppReplicaLease } from "./owner.js";
|
|
10
|
+
import { eraseAppInstallationData, eraseAppCollectionAccess } from "./sign-out-erase.js";
|
|
11
|
+
import { mdbaseError } from "../errors.js";
|
|
12
|
+
const closedView = Object.freeze({ status: "unselected", problem: null, transport: null, live: null });
|
|
13
|
+
const failure = (reason) => new AppInstallationSignInError(reason);
|
|
14
|
+
const liveOutcomes = new Set(["collection_not_yet_migrated", "collection_migrating", "account_suspended", "update_required"]);
|
|
15
|
+
export class AppWebSignInSession {
|
|
16
|
+
lifetime = new AbortController();
|
|
17
|
+
// Origin store closes only AFTER native shutdown, not on the host abort.
|
|
18
|
+
// Replaced by signOut, so Sign in works again in the same session.
|
|
19
|
+
flowLifetime = new AbortController();
|
|
20
|
+
options;
|
|
21
|
+
environment;
|
|
22
|
+
listeners = new Set();
|
|
23
|
+
flow = null;
|
|
24
|
+
host = null;
|
|
25
|
+
installation = null;
|
|
26
|
+
installationLease = null;
|
|
27
|
+
/** Every collection this session holds open (or failed to open). Pages of
|
|
28
|
+
* the app may each show a different one; `focus` is the one `getSnapshot`
|
|
29
|
+
* shows (the last `select`). Each has its own native host and lease. */
|
|
30
|
+
slots = new Map();
|
|
31
|
+
focus = null;
|
|
32
|
+
/** The slot the current operation is opening, for its failure handling. */
|
|
33
|
+
openingSlot = null;
|
|
34
|
+
abortCollections = () => { for (const slot of this.slots.values())
|
|
35
|
+
slot.lifetime?.abort(); };
|
|
36
|
+
/** Sign-in state shared by every collection; `selectedCollectionId` stays null. */
|
|
37
|
+
base = Object.freeze({ status: "not_started", signIn: null, collections: Object.freeze([]), selectedCollectionId: null, problem: null, timing: null });
|
|
38
|
+
snapshotValue = this.base;
|
|
39
|
+
authorizationStartedAt = null;
|
|
40
|
+
authorizationRetryAt = 0;
|
|
41
|
+
authorizationRateLimit = null;
|
|
42
|
+
pending = null;
|
|
43
|
+
/** The background approval poll currently occupying `pending`, if any. */
|
|
44
|
+
polling = null;
|
|
45
|
+
timer = null;
|
|
46
|
+
closing = null;
|
|
47
|
+
foreground = true;
|
|
48
|
+
receiptRead = null;
|
|
49
|
+
foregroundRead = null;
|
|
50
|
+
attested = false;
|
|
51
|
+
acknowledged = false;
|
|
52
|
+
consentPending = false;
|
|
53
|
+
fileAccess = null;
|
|
54
|
+
freshApproval = false;
|
|
55
|
+
/** The window this session's approval (or file access request) is shown in. */
|
|
56
|
+
approvalWindow = null;
|
|
57
|
+
nativePending = null;
|
|
58
|
+
forgotten = new Set();
|
|
59
|
+
removedScopes = new Set();
|
|
60
|
+
onAbort = () => { void this.close().catch(() => { }); };
|
|
61
|
+
constructor(options) {
|
|
62
|
+
this.options = Object.freeze({ ...options });
|
|
63
|
+
// Validate the authenticated environment before touching storage or HTTP.
|
|
64
|
+
this.environment = selectAppEnvironment({ environment: options.environment, appOrigin: options.origin, platform: options.allowNativeLoopbackHttp ? "native" : undefined, release: options.release });
|
|
65
|
+
options.signal.addEventListener("abort", this.onAbort, { once: true });
|
|
66
|
+
this.lifetime.signal.addEventListener("abort", this.abortCollections, { once: true });
|
|
67
|
+
}
|
|
68
|
+
getSnapshot() { return this.snapshotValue; }
|
|
69
|
+
snapshot() { return this.getSnapshot(); }
|
|
70
|
+
subscribe(listener) { this.listeners.add(listener); return () => { this.listeners.delete(listener); }; }
|
|
71
|
+
/** The snapshot a page showing `collectionId` (null: none) sees: the shared
|
|
72
|
+
* sign-in state, with that collection's status while sign-in is settled. */
|
|
73
|
+
viewFor(collectionId, options = {}) {
|
|
74
|
+
// `bystander`: the page did not start the approval in progress. Adding a
|
|
75
|
+
// collection keeps the open ones open, so its page keeps showing its own.
|
|
76
|
+
if (options.bystander && this.base.status === "authorizing" && this.consentPending && collectionId !== null && this.slots.has(collectionId))
|
|
77
|
+
return this.compose(collectionId, true);
|
|
78
|
+
if (collectionId === this.focus)
|
|
79
|
+
return this.snapshotValue;
|
|
80
|
+
return this.compose(collectionId);
|
|
81
|
+
}
|
|
82
|
+
/** The open collection's own view, or null when this session does not hold it. */
|
|
83
|
+
collectionView(collectionId) { return this.slots.get(collectionId)?.view ?? null; }
|
|
84
|
+
/** Collections this session holds (open, opening or failed to open). */
|
|
85
|
+
heldCollections() { return [...this.slots.keys()]; }
|
|
86
|
+
compose(collectionId, settled = false) {
|
|
87
|
+
const base = this.base, slot = collectionId === null ? undefined : this.slots.get(collectionId);
|
|
88
|
+
if (!slot)
|
|
89
|
+
return base;
|
|
90
|
+
if (base.status !== "unselected" && !settled)
|
|
91
|
+
return Object.freeze({ ...base, selectedCollectionId: slot.id, transport: slot.view.transport, live: slot.view.live });
|
|
92
|
+
const { problemDetail: _shared, ...shared } = base, { problemDetail, ...view } = slot.view;
|
|
93
|
+
return Object.freeze({ ...shared, ...(settled ? { status: "unselected", problem: null, approval: null } : {}), ...view, selectedCollectionId: slot.id, ...(problemDetail ? { problemDetail } : {}) });
|
|
94
|
+
}
|
|
95
|
+
/** The connection of an open collection (default: the focused one). Null
|
|
96
|
+
* while the sign-in is not settled (signing in, blocked) or it is not open. */
|
|
97
|
+
connection(collectionId = this.focus) {
|
|
98
|
+
const slot = collectionId === null ? undefined : this.slots.get(collectionId);
|
|
99
|
+
const settled = this.base.status === "unselected" || (this.base.status === "authorizing" && this.consentPending);
|
|
100
|
+
if (!slot || this.closing || this.options.signal.aborted || !slot.usable || slot.lifetime?.signal.aborted || !this.installation?.isCurrent() || !settled
|
|
101
|
+
|| !["ready", "setup_required"].includes(slot.view.status) || !this.sameScope(slot.scope, slot.leaseScope) || slot.scope?.collection !== slot.id)
|
|
102
|
+
return null;
|
|
103
|
+
return slot.selected?.connection ?? null;
|
|
104
|
+
}
|
|
105
|
+
sameScope(a, b) {
|
|
106
|
+
return a !== null && b !== null && a.account === b.account && a.installation === b.installation && a.collection === b.collection
|
|
107
|
+
&& a.account === this.installation?.scope.account && a.installation === this.installation?.scope.installation;
|
|
108
|
+
}
|
|
109
|
+
directAccess = appBrowserDirectAccess;
|
|
110
|
+
checkDirectAccess(options) {
|
|
111
|
+
this.check();
|
|
112
|
+
return this.directAccess.check(options);
|
|
113
|
+
}
|
|
114
|
+
requestDirectAccess(options) {
|
|
115
|
+
this.check();
|
|
116
|
+
return this.directAccess.request(options);
|
|
117
|
+
}
|
|
118
|
+
check() { if (this.closing || this.options.signal.aborted || this.lifetime.signal.aborted)
|
|
119
|
+
throw failure("fenced"); }
|
|
120
|
+
/** Shared sign-in state (never a collection's status; see publishSlot). */
|
|
121
|
+
publish(update) {
|
|
122
|
+
this.check();
|
|
123
|
+
this.setBase(update);
|
|
124
|
+
this.changed();
|
|
125
|
+
}
|
|
126
|
+
setBase(update) {
|
|
127
|
+
const { problemDetail: previousDetail, ...previous } = this.base;
|
|
128
|
+
const detail = update.problem === null ? undefined : update.problemDetail ?? previousDetail;
|
|
129
|
+
this.base = Object.freeze({ ...previous, ...update, selectedCollectionId: null, signIn: this.flow?.view() ?? null, ...(detail ? { problemDetail: detail } : {}) });
|
|
130
|
+
}
|
|
131
|
+
/** One open collection's status, problem and transport. */
|
|
132
|
+
publishSlot(slot, update) {
|
|
133
|
+
this.check();
|
|
134
|
+
if (this.slots.get(slot.id) !== slot)
|
|
135
|
+
return;
|
|
136
|
+
let timing = this.base.timing;
|
|
137
|
+
if (this.authorizationStartedAt !== null && (update.status === "ready" || update.status === "setup_required")) {
|
|
138
|
+
const elapsed = Math.max(0, performance.now() - this.authorizationStartedAt);
|
|
139
|
+
timing = Object.freeze({ firstScreenMs: timing?.firstScreenMs ?? elapsed, readyMs: update.status === "ready" ? timing?.readyMs ?? elapsed : timing?.readyMs ?? null });
|
|
140
|
+
}
|
|
141
|
+
this.setBase({ timing });
|
|
142
|
+
const { problemDetail: previousDetail, ...previous } = slot.view;
|
|
143
|
+
const detail = update.problem === null ? undefined : update.problemDetail ?? previousDetail;
|
|
144
|
+
const openingProgress = (update.status ?? previous.status) === "opening" ? ("openingProgress" in update ? update.openingProgress ?? null : previous.openingProgress ?? null) : null;
|
|
145
|
+
slot.view = Object.freeze({ ...previous, ...update, openingProgress, ...(detail ? { problemDetail: detail } : {}) });
|
|
146
|
+
this.changed();
|
|
147
|
+
}
|
|
148
|
+
changed() {
|
|
149
|
+
this.snapshotValue = this.compose(this.focus);
|
|
150
|
+
for (const listener of [...this.listeners]) {
|
|
151
|
+
try {
|
|
152
|
+
listener();
|
|
153
|
+
}
|
|
154
|
+
catch { /* subscriber cannot interrupt durable lifecycle */ }
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Background approval read; a sign-in gesture may wait for it (authorize). */
|
|
158
|
+
poll(work) {
|
|
159
|
+
if (this.pending)
|
|
160
|
+
return;
|
|
161
|
+
void this.operation(work).catch(() => { });
|
|
162
|
+
this.polling = this.pending;
|
|
163
|
+
}
|
|
164
|
+
stopPolling() { if (this.timer !== null)
|
|
165
|
+
clearTimeout(this.timer); this.timer = null; }
|
|
166
|
+
/** `contained`: a failure rejects the caller only; the session stays as it was. */
|
|
167
|
+
operation(work, contained = false) {
|
|
168
|
+
this.check();
|
|
169
|
+
if (this.pending)
|
|
170
|
+
return Promise.reject(failure("busy"));
|
|
171
|
+
this.foregroundRead = null;
|
|
172
|
+
this.stopPolling();
|
|
173
|
+
const workResult = Promise.resolve().then(() => { this.check(); return work(); });
|
|
174
|
+
// Keep cleanup in the original occupied operation. close() must await it,
|
|
175
|
+
// not race a second native/SQL/lease stop against a rejected work promise.
|
|
176
|
+
const pending = workResult.catch(async (error) => {
|
|
177
|
+
if (!contained && !this.closing && !this.options.signal.aborted) {
|
|
178
|
+
const { problem, detail } = webSignInProblem(error);
|
|
179
|
+
if (problem === "open_failed") {
|
|
180
|
+
try {
|
|
181
|
+
console.error("mdbase web sign-in open failed", detail.name, detail.code);
|
|
182
|
+
}
|
|
183
|
+
catch { /* Diagnostics must never replace the original failure. */ }
|
|
184
|
+
}
|
|
185
|
+
// A failed open blocks that collection only; other pages keep theirs.
|
|
186
|
+
const slot = this.openingSlot;
|
|
187
|
+
this.openingSlot = null;
|
|
188
|
+
if (slot && this.slots.get(slot.id) === slot) {
|
|
189
|
+
let retryableChallenge = false;
|
|
190
|
+
try {
|
|
191
|
+
retryableChallenge = error instanceof AppCloudCopyBootstrapError && error.reason === "unavailable" && error.retryable === true &&
|
|
192
|
+
slot.view.status === "opening" && this.base.collections.some(c => c.collectionId === slot.id) &&
|
|
193
|
+
this.flow?.view().state === "paired" && this.installation?.isCurrent() === true;
|
|
194
|
+
}
|
|
195
|
+
catch { /* no inferred retry authority */ }
|
|
196
|
+
if (retryableChallenge) {
|
|
197
|
+
try {
|
|
198
|
+
await this.closeSlot(slot);
|
|
199
|
+
this.check();
|
|
200
|
+
}
|
|
201
|
+
catch (stopError) {
|
|
202
|
+
if (!this.closing && !this.options.signal.aborted)
|
|
203
|
+
this.publishSlot(slot, { status: "blocked", problem: "recovery_required", problemDetail: webSignInProblem(stopError).detail });
|
|
204
|
+
throw stopError; // failed stop keeps original scope/leases quarantined
|
|
205
|
+
}
|
|
206
|
+
this.publishSlot(slot, { status: "unselected", problem, problemDetail: detail });
|
|
207
|
+
}
|
|
208
|
+
else
|
|
209
|
+
this.publishSlot(slot, { status: "blocked", problem, problemDetail: detail });
|
|
210
|
+
}
|
|
211
|
+
else
|
|
212
|
+
this.publish({ status: "blocked", problem, problemDetail: detail });
|
|
213
|
+
}
|
|
214
|
+
throw error;
|
|
215
|
+
});
|
|
216
|
+
this.pending = pending;
|
|
217
|
+
return pending.finally(() => { if (this.pending === pending)
|
|
218
|
+
this.pending = null; this.schedulePoll(); });
|
|
219
|
+
}
|
|
220
|
+
/** Atomic create-or-restore; never recover a malformed ledger as fresh. A
|
|
221
|
+
* completed installation restores locally. No Connect request before the
|
|
222
|
+
* sign-in gesture; a pending ledger keeps its SAME request for authorize(). */
|
|
223
|
+
start() {
|
|
224
|
+
return this.operation(async () => {
|
|
225
|
+
if (this.flow)
|
|
226
|
+
return this.getSnapshot();
|
|
227
|
+
this.publish({ status: "starting", problem: null, signOutResult: null });
|
|
228
|
+
const p = this.options;
|
|
229
|
+
this.flow = await AppProtectedInstallationSignIn.open({ ...p, mode: p.storeMode ?? "open", signal: this.flowLifetime.signal,
|
|
230
|
+
environmentSelection: this.environment });
|
|
231
|
+
this.check();
|
|
232
|
+
// Local ledger only: the pairing request is created by the sign-in
|
|
233
|
+
// gesture (authorize), never by a page load.
|
|
234
|
+
const view = this.flow.view();
|
|
235
|
+
if (view.state === "paired") {
|
|
236
|
+
if (this.flow.pendingNativeSelection?.() && !view.nativeSelection)
|
|
237
|
+
throw failure("recovery_required");
|
|
238
|
+
// Restored scoped actors load only their OWN protected metadata here.
|
|
239
|
+
// Their ordinary native receipt/ACK/custody opens when selected; never
|
|
240
|
+
// initialize one native engine per restored recovery reference.
|
|
241
|
+
await this.openDevice(false, this.options.recoveryFor !== undefined);
|
|
242
|
+
if (this.flow.collectionConsentView()?.state === "pending") {
|
|
243
|
+
this.consentPending = true;
|
|
244
|
+
this.publish({ status: "authorizing" });
|
|
245
|
+
}
|
|
246
|
+
else
|
|
247
|
+
await this.refreshCollections();
|
|
248
|
+
}
|
|
249
|
+
else
|
|
250
|
+
this.publish({ status: view.state === "pending" ? "signed_out" : "authorizing" });
|
|
251
|
+
return this.getSnapshot();
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
/** Call from the app's single sign-in user gesture after start(). No manual
|
|
255
|
+
* exchange, confirmation or attestation controls are needed by consumers. */
|
|
256
|
+
authorize(options = {}) {
|
|
257
|
+
this.check();
|
|
258
|
+
if (this.authorizationRateLimit && Date.now() < this.authorizationRetryAt)
|
|
259
|
+
return Promise.reject(this.authorizationRateLimit);
|
|
260
|
+
const poll = this.pending !== null && this.pending === this.polling ? this.pending : null;
|
|
261
|
+
if (!this.flow || (this.pending && !poll))
|
|
262
|
+
return Promise.reject(failure("busy"));
|
|
263
|
+
const portal = this.options.openPortal();
|
|
264
|
+
if (!poll)
|
|
265
|
+
return this.beginAuthorization(portal, options);
|
|
266
|
+
// A background approval poll holds the session: let it settle, then use
|
|
267
|
+
// this gesture's window. Only a session still waiting for approval restarts.
|
|
268
|
+
return poll.catch(() => { }).then(() => {
|
|
269
|
+
try {
|
|
270
|
+
this.check();
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
portal.close();
|
|
274
|
+
throw error;
|
|
275
|
+
}
|
|
276
|
+
if (this.pending) {
|
|
277
|
+
portal.close();
|
|
278
|
+
throw failure("busy");
|
|
279
|
+
}
|
|
280
|
+
const status = this.base.status;
|
|
281
|
+
if (status !== "authorizing" && status !== "signed_out") {
|
|
282
|
+
portal.close();
|
|
283
|
+
return this.getSnapshot();
|
|
284
|
+
}
|
|
285
|
+
return this.beginAuthorization(portal, options);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
beginAuthorization(portal, options) {
|
|
289
|
+
const hint = { collectionHint: options.collectionHint ?? null };
|
|
290
|
+
const view = this.flow.view();
|
|
291
|
+
this.authorizationStartedAt = performance.now();
|
|
292
|
+
this.publish({ timing: Object.freeze({ firstScreenMs: null, readyMs: null }), approval: null });
|
|
293
|
+
return this.operation(async () => {
|
|
294
|
+
try {
|
|
295
|
+
if (view.state === "paired") {
|
|
296
|
+
if (this.flow.pendingNativeSelection?.() && !view.nativeSelection)
|
|
297
|
+
throw failure("recovery_required");
|
|
298
|
+
await this.openDevice();
|
|
299
|
+
this.check();
|
|
300
|
+
const consent = await this.flow.startCollectionConsent(this.installation, this.options.requestedCreateCollections ?? this.options.freshRequestedCreateCollections ?? false, hint);
|
|
301
|
+
this.check();
|
|
302
|
+
this.consentPending = true;
|
|
303
|
+
portal.navigate(consent.verificationUri);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
const started = await this.flow.start(hint).catch(error => this.renewFromGesture(error));
|
|
307
|
+
this.check();
|
|
308
|
+
portal.navigate(started.verificationUri);
|
|
309
|
+
}
|
|
310
|
+
this.holdApprovalWindow(portal);
|
|
311
|
+
this.publish({ status: "authorizing", problem: null });
|
|
312
|
+
await this.advance();
|
|
313
|
+
return this.getSnapshot();
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
if (error instanceof AppInstallationSignInError && error.server?.status === 429) {
|
|
317
|
+
this.authorizationRateLimit = error;
|
|
318
|
+
this.authorizationRetryAt = Date.now() + Math.min(MAX_SERVER_RETRY_MS, Math.max(MIN_SERVER_RETRY_MS, error.server.retryAfterMs ?? 30_000));
|
|
319
|
+
}
|
|
320
|
+
portal.close();
|
|
321
|
+
throw error;
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
/** From the app's user gesture: ask for declared optional file actions on an
|
|
326
|
+
* approved collection. The open collection stays open; the outcome arrives
|
|
327
|
+
* through pollFileAccess. A refusal leaves the session unchanged. */
|
|
328
|
+
requestFileAccess(collectionId, actions, reason) {
|
|
329
|
+
this.check();
|
|
330
|
+
if (!this.flow || this.pending)
|
|
331
|
+
return Promise.reject(failure("busy"));
|
|
332
|
+
const portal = this.options.openPortal();
|
|
333
|
+
return this.operation(async () => {
|
|
334
|
+
try {
|
|
335
|
+
if (this.flow.view().state !== "paired" || !this.installation || !this.base.collections.some(c => c.collectionId === collectionId))
|
|
336
|
+
throw failure("refused");
|
|
337
|
+
const request = await this.flow.startFileAccess(this.installation, collectionId, actions, reason);
|
|
338
|
+
this.check();
|
|
339
|
+
this.fileAccess = request;
|
|
340
|
+
portal.navigate(request.verificationUri);
|
|
341
|
+
this.holdApprovalWindow(portal);
|
|
342
|
+
this.publish({ fileAccess: Object.freeze({ requestId: request.requestId, collectionId, actions: request.actions, state: "pending" }) });
|
|
343
|
+
return this.getSnapshot();
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
portal.close();
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
}, true);
|
|
350
|
+
}
|
|
351
|
+
/** One read of the current file access request. Lost reads stay pending
|
|
352
|
+
* until the request expires; a busy session answers with the current view. */
|
|
353
|
+
pollFileAccess(requestId) {
|
|
354
|
+
const request = this.fileAccess;
|
|
355
|
+
if (!request || request.requestId !== requestId || this.pending || !this.flow || !this.installation)
|
|
356
|
+
return Promise.resolve(this.getSnapshot());
|
|
357
|
+
return this.operation(async () => {
|
|
358
|
+
let outcome = { state: "pending" };
|
|
359
|
+
try {
|
|
360
|
+
outcome = await this.flow.exchangeFileAccess(this.installation, request);
|
|
361
|
+
}
|
|
362
|
+
catch { /* still pending until it expires */ }
|
|
363
|
+
this.check();
|
|
364
|
+
if (this.fileAccess !== request || (outcome.state === "pending" && Date.now() < request.expiresAt))
|
|
365
|
+
return this.getSnapshot();
|
|
366
|
+
this.fileAccess = null;
|
|
367
|
+
this.closeApprovalWindow();
|
|
368
|
+
const granted = outcome.state === "granted" ? outcome.actions : null;
|
|
369
|
+
const collections = granted ? Object.freeze(this.base.collections.map(c => c.collectionId !== request.collectionId ? c
|
|
370
|
+
: Object.freeze({ ...c, fileActions: Object.freeze([...new Set([...(c.fileActions ?? []), ...granted])]) }))) : this.base.collections;
|
|
371
|
+
this.publish({ collections, fileAccess: Object.freeze({ requestId, collectionId: request.collectionId, actions: granted ?? request.actions, state: outcome.state === "pending" ? "expired" : outcome.state }) });
|
|
372
|
+
return this.getSnapshot();
|
|
373
|
+
}, true);
|
|
374
|
+
}
|
|
375
|
+
/** This sign-in gesture renews a window that expired or was cancelled in the
|
|
376
|
+
* portal. The flow decides renewability; otherwise the original error stands. */
|
|
377
|
+
async renewFromGesture(error) {
|
|
378
|
+
if (!(error instanceof AppInstallationSignInError) || (error.reason !== "expired" && error.reason !== "refused"))
|
|
379
|
+
throw error;
|
|
380
|
+
try {
|
|
381
|
+
return await this.flow.renewExpiredPairing();
|
|
382
|
+
}
|
|
383
|
+
catch (renewal) {
|
|
384
|
+
throw renewal instanceof AppInstallationSignInError && renewal.reason === "recovery_required" ? error : renewal;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
/** A typed expired window renews only from an explicit user gesture. Unknown
|
|
388
|
+
* HTTP outcomes never cause automatic renewal, new keys or another actor. */
|
|
389
|
+
renewExpiredPairing() {
|
|
390
|
+
return this.operation(async () => {
|
|
391
|
+
if (!this.flow)
|
|
392
|
+
throw failure("binding");
|
|
393
|
+
await this.flow.renewExpiredPairing();
|
|
394
|
+
this.check();
|
|
395
|
+
this.publish({ status: "signed_out", problem: null });
|
|
396
|
+
return this.getSnapshot();
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
/** Only SAME-secret receipt reads may retry transient HTTP loss. START,
|
|
400
|
+
* native attestation, custody and unknown mutations never use this path. */
|
|
401
|
+
receiptGeneration(flow) {
|
|
402
|
+
try {
|
|
403
|
+
if (!flow.isCurrent())
|
|
404
|
+
return null;
|
|
405
|
+
const view = flow.view(), consent = this.consentPending ? flow.collectionConsentView() : null;
|
|
406
|
+
if (this.consentPending ? consent?.state !== "pending" : !["pending", "awaiting_approval"].includes(view.state))
|
|
407
|
+
return null;
|
|
408
|
+
return JSON.stringify([view.requestId, view.installationId, view.deviceId, view.accountId, view.state,
|
|
409
|
+
this.consentPending, consent?.requestId, consent?.state]);
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
return null;
|
|
413
|
+
} // Optional latency shortcut cannot replace a rejection.
|
|
414
|
+
}
|
|
415
|
+
currentReceipt(read) {
|
|
416
|
+
try {
|
|
417
|
+
return !this.closing && !this.lifetime.signal.aborted && !this.flowLifetime.signal.aborted && !read.caller.aborted &&
|
|
418
|
+
this.options.signal === read.caller && this.flow === read.flow && this.installation === read.installation &&
|
|
419
|
+
(read.installation === null || read.installation.isCurrent() === true) &&
|
|
420
|
+
this.attested === read.attested && this.acknowledged === read.acknowledged &&
|
|
421
|
+
this.receiptGeneration(read.flow) === read.generation;
|
|
422
|
+
}
|
|
423
|
+
catch {
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
async exchangeReceipt(read) {
|
|
428
|
+
const flow = this.flow, operation = this.pending, generation = flow ? this.receiptGeneration(flow) : null;
|
|
429
|
+
const slot = flow && operation && generation !== null ? Object.freeze({
|
|
430
|
+
flow, operation, generation, caller: this.options.signal, installation: this.installation,
|
|
431
|
+
attested: this.attested, acknowledged: this.acknowledged,
|
|
432
|
+
}) : null;
|
|
433
|
+
this.receiptRead = slot;
|
|
434
|
+
let completed = false;
|
|
435
|
+
try {
|
|
436
|
+
const value = await read();
|
|
437
|
+
completed = value !== null && value !== undefined;
|
|
438
|
+
return value;
|
|
439
|
+
}
|
|
440
|
+
catch (error) {
|
|
441
|
+
if (error instanceof AppInstallationSignInError && error.reason === "outcome_unknown" && this.flow?.isCurrent()) {
|
|
442
|
+
this.publish({ status: "authorizing", problem: "outcome_unknown" });
|
|
443
|
+
return null;
|
|
444
|
+
}
|
|
445
|
+
throw error;
|
|
446
|
+
}
|
|
447
|
+
finally {
|
|
448
|
+
if (this.receiptRead === slot)
|
|
449
|
+
this.receiptRead = null;
|
|
450
|
+
if (this.foregroundRead === slot && (!completed || !slot || !this.currentReceipt(slot)))
|
|
451
|
+
this.foregroundRead = null;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
async advance() {
|
|
455
|
+
if (this.consentPending) {
|
|
456
|
+
let consent;
|
|
457
|
+
try {
|
|
458
|
+
consent = await this.exchangeReceipt(() => this.flow.exchangeCollectionConsent(this.installation));
|
|
459
|
+
}
|
|
460
|
+
catch (error) {
|
|
461
|
+
// Already signed in: a re-consent denied or expired in Connect is a
|
|
462
|
+
// cancellation, never a blocked sign-in. Back to the collections view.
|
|
463
|
+
if (!(error instanceof AppInstallationSignInError) || (error.reason !== "refused" && error.reason !== "expired"))
|
|
464
|
+
throw error;
|
|
465
|
+
// Leave "authorizing" in the same publication that ends the consent:
|
|
466
|
+
// pages that did not start it never see a sign-in for their collection.
|
|
467
|
+
this.check();
|
|
468
|
+
this.consentPending = false;
|
|
469
|
+
this.closeApprovalWindow();
|
|
470
|
+
this.publish({ status: "unselected", problem: null, approval: Object.freeze({ outcome: "cancelled" }) });
|
|
471
|
+
await this.refreshCollections();
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
this.check();
|
|
475
|
+
if (!consent)
|
|
476
|
+
return;
|
|
477
|
+
if (consent.state === "scope_updated") {
|
|
478
|
+
if (consent.accountSelectionConfirmed !== true)
|
|
479
|
+
throw failure("account_confirmation_required");
|
|
480
|
+
const native = this.flow.pendingNativeSelection?.();
|
|
481
|
+
if (native?.requestId === consent.requestId)
|
|
482
|
+
await this.finishNativeChoice(native);
|
|
483
|
+
else if (this.flow.view().collectionSelection?.requestId !== consent.requestId)
|
|
484
|
+
throw failure("response");
|
|
485
|
+
this.consentPending = false;
|
|
486
|
+
this.freshApproval = true;
|
|
487
|
+
this.closeApprovalWindow();
|
|
488
|
+
await this.refreshCollections();
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
await this.prepareNativeChoice();
|
|
492
|
+
this.publish({ status: "authorizing", problem: null });
|
|
493
|
+
}
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
let view = await this.exchangeReceipt(() => this.flow.exchange());
|
|
497
|
+
this.check();
|
|
498
|
+
if (!view)
|
|
499
|
+
return;
|
|
500
|
+
if (view.state === "account_selected") {
|
|
501
|
+
// This consumes only the current SDK-owned, portal-confirmed selection.
|
|
502
|
+
// A view/account ID supplied by an app is not an authority capability.
|
|
503
|
+
view = await this.flow.confirmPortalSelectedAccount();
|
|
504
|
+
this.check();
|
|
505
|
+
}
|
|
506
|
+
if (view.state === "account_confirmed" || view.state === "awaiting_approval") {
|
|
507
|
+
await this.openDevice();
|
|
508
|
+
this.check();
|
|
509
|
+
if (!this.attested) {
|
|
510
|
+
await this.host.attestInstallation();
|
|
511
|
+
this.check();
|
|
512
|
+
this.attested = true;
|
|
513
|
+
}
|
|
514
|
+
await this.prepareNativeChoice();
|
|
515
|
+
}
|
|
516
|
+
if (view.state === "paired") {
|
|
517
|
+
const native = this.flow.pendingNativeSelection?.();
|
|
518
|
+
if (native?.requestId === view.requestId)
|
|
519
|
+
await this.finishNativeChoice(native);
|
|
520
|
+
else if (view.collectionSelection?.requestId !== view.requestId)
|
|
521
|
+
throw failure("response");
|
|
522
|
+
this.freshApproval = true;
|
|
523
|
+
this.closeApprovalWindow();
|
|
524
|
+
await this.openDevice();
|
|
525
|
+
this.check();
|
|
526
|
+
await this.refreshCollections();
|
|
527
|
+
}
|
|
528
|
+
else
|
|
529
|
+
this.publish({ status: "authorizing", problem: null });
|
|
530
|
+
}
|
|
531
|
+
/** Preparation is optional and never blocks a genuine Hosted approval. Only
|
|
532
|
+
* the original lifecycle turn attaches after observing its matching context. */
|
|
533
|
+
async prepareNativeChoice() {
|
|
534
|
+
const port = this.approvalWindow?.nativeAuthorization;
|
|
535
|
+
if (!port || !this.installation)
|
|
536
|
+
return;
|
|
537
|
+
const context = this.flow.nativeAuthorizationContext(this.installation);
|
|
538
|
+
if (!context)
|
|
539
|
+
return;
|
|
540
|
+
let slot = this.nativePending;
|
|
541
|
+
if (!slot) {
|
|
542
|
+
slot = { context, port, life: new AbortController(), prepared: null, failed: false, attempted: false };
|
|
543
|
+
this.nativePending = slot;
|
|
544
|
+
if (context.authorizationId) {
|
|
545
|
+
slot.failed = true;
|
|
546
|
+
return;
|
|
547
|
+
} // lost original keys: never regenerate
|
|
548
|
+
const original = slot;
|
|
549
|
+
const signal = AbortSignal.any([this.lifetime.signal, this.flowLifetime.signal, slot.life.signal]);
|
|
550
|
+
void port.prepare(context, signal).then(prepared => {
|
|
551
|
+
if (this.nativePending !== original || signal.aborted)
|
|
552
|
+
return;
|
|
553
|
+
original.prepared = Object.freeze({ ...prepared });
|
|
554
|
+
}, () => { original.failed = true; });
|
|
555
|
+
}
|
|
556
|
+
if (slot.context.requestId !== context.requestId || slot.context.accountId !== context.accountId || slot.context.challenge !== context.challenge)
|
|
557
|
+
throw failure("fenced");
|
|
558
|
+
if (slot.prepared && !slot.attempted) {
|
|
559
|
+
slot.attempted = true;
|
|
560
|
+
try {
|
|
561
|
+
await this.flow.attachNativeAuthorization(this.installation, slot.context, slot.prepared);
|
|
562
|
+
this.check();
|
|
563
|
+
}
|
|
564
|
+
catch {
|
|
565
|
+
slot.failed = true;
|
|
566
|
+
} // closed Hosted parent/unknown: actual receipt decides; never replay
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
async finishNativeChoice(selection) {
|
|
570
|
+
const slot = this.nativePending;
|
|
571
|
+
if (!slot || !slot.prepared || !slot.attempted || slot.context.requestId !== selection.requestId || slot.prepared.authorizationId !== selection.authorizationRequestId)
|
|
572
|
+
throw failure("recovery_required");
|
|
573
|
+
await this.openDevice();
|
|
574
|
+
this.check();
|
|
575
|
+
const completion = await slot.port.finish(selection, AbortSignal.any([this.lifetime.signal, this.flowLifetime.signal, slot.life.signal]));
|
|
576
|
+
this.check();
|
|
577
|
+
if (this.nativePending !== slot || !this.acknowledged || !this.installation)
|
|
578
|
+
throw failure("fenced");
|
|
579
|
+
await this.flow.completeNativeAuthorization(this.installation, completion);
|
|
580
|
+
this.check();
|
|
581
|
+
}
|
|
582
|
+
holdApprovalWindow(portal) {
|
|
583
|
+
if (this.approvalWindow !== portal)
|
|
584
|
+
this.closeApprovalWindow();
|
|
585
|
+
this.approvalWindow = portal;
|
|
586
|
+
}
|
|
587
|
+
/** Approval observed: the opener closes the approval window (the Connect page
|
|
588
|
+
* cannot be relied on to close itself); the window adapter refocuses the app. */
|
|
589
|
+
closeApprovalWindow() {
|
|
590
|
+
const portal = this.approvalWindow;
|
|
591
|
+
this.approvalWindow = null;
|
|
592
|
+
const native = this.nativePending;
|
|
593
|
+
this.nativePending = null;
|
|
594
|
+
native?.life.abort();
|
|
595
|
+
try {
|
|
596
|
+
native?.port.cancel();
|
|
597
|
+
}
|
|
598
|
+
catch { /* cancellation cannot replace the original custody drain */ }
|
|
599
|
+
if (!portal)
|
|
600
|
+
return;
|
|
601
|
+
try {
|
|
602
|
+
portal.close();
|
|
603
|
+
}
|
|
604
|
+
catch { /* already closed by the person */ }
|
|
605
|
+
}
|
|
606
|
+
/** The installation's device: a native host for sign-in work, and one per
|
|
607
|
+
* open collection (`forCollection`). An acknowledged installation whose
|
|
608
|
+
* collections already hold hosts needs no spare one for sign-in. */
|
|
609
|
+
async openDevice(forCollection = false, metadataOnly = false) {
|
|
610
|
+
if (!this.installation) {
|
|
611
|
+
const selected = this.flow.confirmedSelection();
|
|
612
|
+
const scope = Object.freeze({ account: selected.accountId, installation: selected.installationId });
|
|
613
|
+
this.installationLease = await acquireAppInstallationLease(this.options.locks, scope, this.lifetime.signal);
|
|
614
|
+
this.check();
|
|
615
|
+
this.installation = Object.freeze({ scope, isCurrent: () => !this.closing && !this.options.signal.aborted && !this.lifetime.signal.aborted && this.installationLease !== null });
|
|
616
|
+
}
|
|
617
|
+
if (metadataOnly)
|
|
618
|
+
return;
|
|
619
|
+
if (!this.host && !forCollection && this.acknowledged && this.flow.view().state === "paired" && [...this.slots.values()].some(slot => slot.host !== null))
|
|
620
|
+
return;
|
|
621
|
+
if (!this.host) {
|
|
622
|
+
this.host = await AppWebCloudCopyHost.openInstallationDevice({ signIn: this.flow, installation: this.installation,
|
|
623
|
+
release: this.options.release, origin: this.options.origin, signal: this.lifetime.signal,
|
|
624
|
+
loadRuntime: this.options.loadRuntime,
|
|
625
|
+
allowLoopbackHttp: this.environment.allowLoopbackHttp, allowNativeLoopbackHttp: this.environment.allowNativeLoopbackHttp });
|
|
626
|
+
this.check();
|
|
627
|
+
this.acknowledged = this.flow.view().state === "paired";
|
|
628
|
+
}
|
|
629
|
+
else if (!this.acknowledged && this.flow.view().state === "paired") {
|
|
630
|
+
await this.host.completeInstallationSignIn();
|
|
631
|
+
this.check();
|
|
632
|
+
this.acknowledged = true;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
async refreshCollections() {
|
|
636
|
+
const collections = await this.flow.listApprovedCollections(this.installation);
|
|
637
|
+
this.check();
|
|
638
|
+
for (const id of this.flow.view().collectionIds)
|
|
639
|
+
if (!collections.some(c => c.collectionId === id))
|
|
640
|
+
this.removedScopes.add(id);
|
|
641
|
+
const visible = Object.freeze(collections.filter(c => !this.forgotten.has(c.collectionId)));
|
|
642
|
+
// Re-approval of a still-approved open collection keeps it open; the
|
|
643
|
+
// same-scope adapter/lease and connection stay current.
|
|
644
|
+
// A collection no longer approved reads unselected (its page offers approval).
|
|
645
|
+
for (const slot of this.slots.values()) {
|
|
646
|
+
if (slot.usable && slot.selected && !visible.some(c => c.collectionId === slot.id)) {
|
|
647
|
+
slot.usable = false;
|
|
648
|
+
slot.lifetime?.abort();
|
|
649
|
+
await this.closeSlot(slot);
|
|
650
|
+
this.check();
|
|
651
|
+
this.deleteSlot(slot);
|
|
652
|
+
continue;
|
|
653
|
+
}
|
|
654
|
+
const open = slot.usable && slot.selected !== null && visible.some(c => c.collectionId === slot.id);
|
|
655
|
+
const { problemDetail: _stale, ...view } = slot.view;
|
|
656
|
+
slot.view = Object.freeze({ ...view, status: open ? slot.selected.state : "unselected", problem: null });
|
|
657
|
+
}
|
|
658
|
+
this.publish({ status: "unselected", collections: visible, problem: null });
|
|
659
|
+
const picked = this.flow.view().collectionSelection?.selectedCollectionId;
|
|
660
|
+
if ((this.options.autoSelect ?? "only") !== "only")
|
|
661
|
+
return;
|
|
662
|
+
if (this.freshApproval && picked && visible.some(c => c.collectionId === picked))
|
|
663
|
+
await this.openSlot(picked, true);
|
|
664
|
+
else if (visible.length === 1)
|
|
665
|
+
await this.openSlot(visible[0].collectionId, true);
|
|
666
|
+
}
|
|
667
|
+
schedulePoll() {
|
|
668
|
+
if (this.pending && !this.closing && !this.options.signal.aborted)
|
|
669
|
+
return; // Keep ONE original occupied slot.
|
|
670
|
+
const read = this.foregroundRead;
|
|
671
|
+
this.foregroundRead = null;
|
|
672
|
+
for (const slot of this.closing || this.options.signal.aborted ? [] : this.slots.values()) {
|
|
673
|
+
const wait = this.retryAfterMs(slot);
|
|
674
|
+
if (wait === null || slot.timer !== null || slot.view.status !== "blocked")
|
|
675
|
+
continue;
|
|
676
|
+
// Server-directed: the collection is being upgraded. Reopen the SAME
|
|
677
|
+
// collection; the app only shows the description.
|
|
678
|
+
slot.timer = setTimeout(() => {
|
|
679
|
+
slot.timer = null;
|
|
680
|
+
if (this.slots.get(slot.id) !== slot || slot.view.status !== "blocked" || slot.view.problem !== "collection_migrating" || this.flow?.view().state !== "paired")
|
|
681
|
+
return;
|
|
682
|
+
void this.operation(() => this.openSlot(slot.id)).catch(() => { });
|
|
683
|
+
}, wait);
|
|
684
|
+
}
|
|
685
|
+
if (this.closing || this.options.signal.aborted || this.timer !== null || this.base.status !== "authorizing")
|
|
686
|
+
return;
|
|
687
|
+
const resume = this.foreground && read && this.currentReceipt(read) ? read : null;
|
|
688
|
+
this.timer = setTimeout(() => {
|
|
689
|
+
this.timer = null;
|
|
690
|
+
this.poll(async () => {
|
|
691
|
+
if (resume && (!this.foreground || !this.currentReceipt(resume)))
|
|
692
|
+
return;
|
|
693
|
+
await this.advanceApproval();
|
|
694
|
+
});
|
|
695
|
+
}, resume ? 0 : !this.foreground ? 10000 : this.base.problem === "outcome_unknown" ? 5000 : 1000);
|
|
696
|
+
}
|
|
697
|
+
/** Server-directed retry (collection_migrating): clamp 5 s..10 min. */
|
|
698
|
+
retryAfterMs(slot) {
|
|
699
|
+
const s = slot.view;
|
|
700
|
+
if (s.problem !== "collection_migrating")
|
|
701
|
+
return null;
|
|
702
|
+
let retry = null;
|
|
703
|
+
try {
|
|
704
|
+
retry = sanitizeAppServerProblem(s.problemDetail?.server)?.retryAfterMs ?? null;
|
|
705
|
+
}
|
|
706
|
+
catch {
|
|
707
|
+
retry = null;
|
|
708
|
+
}
|
|
709
|
+
return Math.min(MAX_SERVER_RETRY_MS, Math.max(MIN_SERVER_RETRY_MS, retry ?? 30_000));
|
|
710
|
+
}
|
|
711
|
+
/** Owners forward visibility changes; Workers have no ambient document.
|
|
712
|
+
* This report does not acquire the authenticated inventory operation slot:
|
|
713
|
+
* the owning WorkerHost serializes revalidation with its lifecycle requests. */
|
|
714
|
+
setForeground(active) {
|
|
715
|
+
this.check();
|
|
716
|
+
const resumed = active && !this.foreground;
|
|
717
|
+
this.foreground = active;
|
|
718
|
+
this.stopPolling();
|
|
719
|
+
if (!active)
|
|
720
|
+
this.foregroundRead = null;
|
|
721
|
+
else if (resumed && this.receiptRead?.operation === this.pending)
|
|
722
|
+
this.foregroundRead = this.receiptRead;
|
|
723
|
+
if (active && this.base.status === "authorizing" && !this.pending)
|
|
724
|
+
this.poll(() => this.advanceApproval());
|
|
725
|
+
else
|
|
726
|
+
this.schedulePoll();
|
|
727
|
+
// Visibility is non-blocking. WorkerHost queues authenticated inventory
|
|
728
|
+
// revalidation with start/select; it must not occupy this operation slot here.
|
|
729
|
+
}
|
|
730
|
+
/** Owners forward a report that the held approval window was closed (a
|
|
731
|
+
* Worker's proxy portal reflects it in `closed`). Read now when idle; a busy
|
|
732
|
+
* session reads at its next scheduled poll. */
|
|
733
|
+
approvalWindowClosed() {
|
|
734
|
+
this.check();
|
|
735
|
+
if (this.pending || this.base.status !== "authorizing" || !this.approvalWindowGone())
|
|
736
|
+
return;
|
|
737
|
+
this.stopPolling();
|
|
738
|
+
this.poll(() => this.advanceApproval());
|
|
739
|
+
}
|
|
740
|
+
approvalWindowGone() {
|
|
741
|
+
const portal = this.approvalWindow;
|
|
742
|
+
try {
|
|
743
|
+
return portal?.closed === true;
|
|
744
|
+
}
|
|
745
|
+
catch {
|
|
746
|
+
return false;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
/** One scheduled approval read. If the held window was already closed, this
|
|
750
|
+
* read is the final one: Connect records an approval before its window
|
|
751
|
+
* closes, so only a still-pending, definite answer ends the wait. */
|
|
752
|
+
async advanceApproval() {
|
|
753
|
+
const portal = this.approvalWindowGone() ? this.approvalWindow : null;
|
|
754
|
+
await this.advance();
|
|
755
|
+
this.check();
|
|
756
|
+
if (!portal || this.approvalWindow !== portal || this.base.status !== "authorizing")
|
|
757
|
+
return;
|
|
758
|
+
// Unknown read outcome: keep the window state and read again next poll.
|
|
759
|
+
if (this.base.problem === "outcome_unknown")
|
|
760
|
+
return;
|
|
761
|
+
this.closeApprovalWindow();
|
|
762
|
+
if (this.consentPending) {
|
|
763
|
+
// Already signed in: a closed add-collection window is a cancellation,
|
|
764
|
+
// not a sign-in problem. Return to the paired collections view.
|
|
765
|
+
this.consentPending = false;
|
|
766
|
+
this.publish({ status: "unselected", problem: null, approval: Object.freeze({ outcome: "closed" }) });
|
|
767
|
+
await this.refreshCollections();
|
|
768
|
+
return;
|
|
769
|
+
}
|
|
770
|
+
this.publish({ status: "signed_out", problem: "approval_window_closed", approval: Object.freeze({ outcome: "closed" }) });
|
|
771
|
+
}
|
|
772
|
+
/** Open `collectionId` as the only open collection (closing any other). */
|
|
773
|
+
select(collectionId) {
|
|
774
|
+
return this.operation(async () => { await this.openSlot(collectionId, true); return this.getSnapshot(); });
|
|
775
|
+
}
|
|
776
|
+
/** Open `collectionId` beside any other open collection: each page of the
|
|
777
|
+
* app may show its own. Already open: a no-op. Resolves with its view. */
|
|
778
|
+
openCollection(collectionId) {
|
|
779
|
+
return this.operation(async () => { await this.openSlot(collectionId); return this.viewFor(collectionId); });
|
|
780
|
+
}
|
|
781
|
+
/** Close one open collection (its adapter, native host and lease); the
|
|
782
|
+
* others stay open. Not held: a no-op. */
|
|
783
|
+
releaseCollection(collectionId) {
|
|
784
|
+
if (!this.slots.has(collectionId))
|
|
785
|
+
return Promise.resolve(this.getSnapshot());
|
|
786
|
+
return this.operation(async () => {
|
|
787
|
+
const slot = this.slots.get(collectionId);
|
|
788
|
+
if (slot) {
|
|
789
|
+
await this.closeSlot(slot);
|
|
790
|
+
this.check();
|
|
791
|
+
this.deleteSlot(slot);
|
|
792
|
+
this.changed();
|
|
793
|
+
}
|
|
794
|
+
return this.getSnapshot();
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
async openSlot(collectionId, only = false) {
|
|
798
|
+
this.check();
|
|
799
|
+
const collection = this.base.collections.find(c => c.collectionId === collectionId);
|
|
800
|
+
if (!collection || this.flow?.view().state !== "paired" || !this.installation)
|
|
801
|
+
throw failure("refused");
|
|
802
|
+
const others = only ? [...this.slots.values()].filter(other => other.id !== collectionId) : [];
|
|
803
|
+
const existing = this.slots.get(collectionId);
|
|
804
|
+
if (existing && existing.usable && existing.selected && !existing.lifetime?.signal.aborted && this.sameScope(existing.scope, existing.leaseScope) && existing.scope?.collection === collectionId) {
|
|
805
|
+
for (const other of others) {
|
|
806
|
+
other.usable = false;
|
|
807
|
+
other.lifetime?.abort();
|
|
808
|
+
}
|
|
809
|
+
this.focus = collectionId;
|
|
810
|
+
this.settleBase();
|
|
811
|
+
this.publishSlot(existing, { status: existing.selected.state, problem: null });
|
|
812
|
+
for (const other of others) {
|
|
813
|
+
await this.closeSlot(other);
|
|
814
|
+
this.check();
|
|
815
|
+
this.deleteSlot(other);
|
|
816
|
+
this.changed();
|
|
817
|
+
}
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
// Quarantine BEFORE publishing a requested target. Snapshot IDs are not the
|
|
821
|
+
// immutable scope of the old adapter/lease, especially after failed shutdown.
|
|
822
|
+
for (const other of others) {
|
|
823
|
+
other.usable = false;
|
|
824
|
+
other.lifetime?.abort();
|
|
825
|
+
}
|
|
826
|
+
const slot = existing ?? { id: collectionId, host: null, lease: null, leaseScope: null, selected: null, scope: null, lifetime: null, usable: false, stopAssessment: null, timer: null, view: closedView };
|
|
827
|
+
slot.usable = false;
|
|
828
|
+
slot.lifetime?.abort();
|
|
829
|
+
this.slots.set(collectionId, slot);
|
|
830
|
+
this.focus = collectionId;
|
|
831
|
+
this.openingSlot = slot;
|
|
832
|
+
this.settleBase();
|
|
833
|
+
this.publishSlot(slot, { status: "opening", problem: null, openingProgress: null });
|
|
834
|
+
for (const other of others) {
|
|
835
|
+
await this.closeSlot(other);
|
|
836
|
+
this.check();
|
|
837
|
+
this.deleteSlot(other);
|
|
838
|
+
this.changed();
|
|
839
|
+
}
|
|
840
|
+
if (slot.lease || slot.selected || slot.host)
|
|
841
|
+
await this.closeSlot(slot);
|
|
842
|
+
this.check();
|
|
843
|
+
await this.openDevice(true);
|
|
844
|
+
this.check();
|
|
845
|
+
// The first open collection takes the sign-in's native host; each further
|
|
846
|
+
// one gets its own host on the SAME installation.
|
|
847
|
+
slot.host = this.host;
|
|
848
|
+
this.host = null;
|
|
849
|
+
const scope = Object.freeze({ ...this.installation.scope, collection: collectionId });
|
|
850
|
+
slot.lease = await acquireAppReplicaLease(this.options.locks, scope, this.lifetime.signal);
|
|
851
|
+
slot.leaseScope = scope;
|
|
852
|
+
this.check();
|
|
853
|
+
slot.lifetime = new AbortController();
|
|
854
|
+
const newlyCreated = this.freshApproval && this.flow.view().collectionSelection?.createdCollectionIds.includes(collectionId) === true;
|
|
855
|
+
const lifetime = slot.lifetime;
|
|
856
|
+
const selected = await this.options.openCollection({ host: slot.host, installation: this.installation, scope, collection,
|
|
857
|
+
setupPolicy: newlyCreated ? "approved-new-collection" : "explicit", signal: lifetime.signal,
|
|
858
|
+
onProgress: progress => {
|
|
859
|
+
if (this.closing || this.slots.get(slot.id) !== slot || slot.lifetime !== lifetime || lifetime.signal.aborted || slot.view.status !== "opening")
|
|
860
|
+
return;
|
|
861
|
+
if (slot.view.openingProgress !== progress)
|
|
862
|
+
this.publishSlot(slot, { openingProgress: progress });
|
|
863
|
+
} });
|
|
864
|
+
slot.selected = selected;
|
|
865
|
+
slot.scope = scope;
|
|
866
|
+
this.check();
|
|
867
|
+
if (selected.state !== "ready" && selected.state !== "setup_required")
|
|
868
|
+
throw failure("response");
|
|
869
|
+
slot.usable = true;
|
|
870
|
+
if (this.openingSlot === slot)
|
|
871
|
+
this.openingSlot = null;
|
|
872
|
+
slot.stopAssessment = selected.subscribe?.(() => {
|
|
873
|
+
if (this.closing || this.slots.get(slot.id) !== slot || !slot.usable || slot.selected !== selected || slot.lifetime?.signal.aborted ||
|
|
874
|
+
!this.sameScope(slot.scope, slot.leaseScope) || slot.scope?.collection !== slot.id)
|
|
875
|
+
return;
|
|
876
|
+
let ended = null;
|
|
877
|
+
try {
|
|
878
|
+
ended = selected.ended ?? null;
|
|
879
|
+
}
|
|
880
|
+
catch {
|
|
881
|
+
ended = null;
|
|
882
|
+
}
|
|
883
|
+
if (ended) {
|
|
884
|
+
this.accessEnded(slot, selected, ended);
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
if (selected.state === "ready" || selected.state === "setup_required")
|
|
888
|
+
this.publishSlot(slot, { status: selected.state, ...this.liveProblem(slot, selected) });
|
|
889
|
+
}) ?? null;
|
|
890
|
+
this.publishSlot(slot, { status: selected.state, transport: null, live: null, openingProgress: null });
|
|
891
|
+
}
|
|
892
|
+
/** Opening a collection settles a blocked sign-in view; it never ends an
|
|
893
|
+
* approval in progress (a page adding a collection keeps waiting for it). */
|
|
894
|
+
settleBase() {
|
|
895
|
+
if (this.base.status === "blocked" || this.base.status === "unselected")
|
|
896
|
+
this.setBase({ status: "unselected", problem: null });
|
|
897
|
+
}
|
|
898
|
+
deleteSlot(slot) {
|
|
899
|
+
if (slot.timer !== null)
|
|
900
|
+
clearTimeout(slot.timer);
|
|
901
|
+
slot.timer = null;
|
|
902
|
+
if (this.slots.get(slot.id) === slot)
|
|
903
|
+
this.slots.delete(slot.id);
|
|
904
|
+
if (this.focus === slot.id)
|
|
905
|
+
this.focus = null;
|
|
906
|
+
if (this.openingSlot === slot)
|
|
907
|
+
this.openingSlot = null;
|
|
908
|
+
}
|
|
909
|
+
/** The log ended access to an open collection. Block it at once (no
|
|
910
|
+
* connection is handed out, so every page showing it stops writing), then
|
|
911
|
+
* stop it, which fences every page's data ports. Local data stays here. */
|
|
912
|
+
accessEnded(slot, selected, reason) {
|
|
913
|
+
if (slot.selected !== selected || !slot.usable)
|
|
914
|
+
return;
|
|
915
|
+
const problem = reason === "gone" ? "collection_deleted" : reason === "revoked" ? "unauthenticated" : "access_removed";
|
|
916
|
+
if (reason !== "gone")
|
|
917
|
+
this.removedScopes.add(slot.id);
|
|
918
|
+
slot.usable = false;
|
|
919
|
+
this.publishSlot(slot, { status: "blocked", problem, transport: null, live: null });
|
|
920
|
+
const stop = () => {
|
|
921
|
+
if (this.closing || this.options.signal.aborted || slot.selected !== selected || this.slots.get(slot.id) !== slot)
|
|
922
|
+
return;
|
|
923
|
+
if (this.pending) {
|
|
924
|
+
void this.pending.catch(() => { }).then(stop);
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
void this.operation(async () => {
|
|
928
|
+
await this.closeSlot(slot);
|
|
929
|
+
this.publishSlot(slot, { status: "blocked", problem });
|
|
930
|
+
// The server closed the socket because access changed: re-read the
|
|
931
|
+
// approved list so a removed or deleted collection drops out of it.
|
|
932
|
+
// A failed read keeps the current list; the block stays either way.
|
|
933
|
+
if (!this.flow || !this.installation || this.flow.view().state !== "paired")
|
|
934
|
+
return;
|
|
935
|
+
try {
|
|
936
|
+
const collections = await this.flow.listApprovedCollections(this.installation);
|
|
937
|
+
this.check();
|
|
938
|
+
this.publish({ collections: Object.freeze(collections.filter(c => !this.forgotten.has(c.collectionId))) });
|
|
939
|
+
}
|
|
940
|
+
catch { /* list refresh is best effort */ }
|
|
941
|
+
}).catch(() => { });
|
|
942
|
+
};
|
|
943
|
+
stop();
|
|
944
|
+
}
|
|
945
|
+
/** Live problem of an open collection: shown while it lasts, cleared after. */
|
|
946
|
+
liveProblem(slot, selected) {
|
|
947
|
+
let server = null;
|
|
948
|
+
try {
|
|
949
|
+
server = selected.problem ?? null;
|
|
950
|
+
}
|
|
951
|
+
catch {
|
|
952
|
+
server = null;
|
|
953
|
+
}
|
|
954
|
+
let health = null;
|
|
955
|
+
try {
|
|
956
|
+
health = selected.health ?? null;
|
|
957
|
+
}
|
|
958
|
+
catch {
|
|
959
|
+
health = null;
|
|
960
|
+
}
|
|
961
|
+
const transport = health ? Object.freeze({ ...health }) : null;
|
|
962
|
+
let live = null;
|
|
963
|
+
try {
|
|
964
|
+
const v = selected.live;
|
|
965
|
+
live = typeof v === "boolean" ? v : null;
|
|
966
|
+
}
|
|
967
|
+
catch {
|
|
968
|
+
live = null;
|
|
969
|
+
}
|
|
970
|
+
const outcome = isAppServerProblem(server) ? appServerOutcome(server) : null;
|
|
971
|
+
if (outcome && server)
|
|
972
|
+
return { problem: outcome, problemDetail: Object.freeze({ name: "AppHttpLogError", code: outcome, server }), transport, live };
|
|
973
|
+
return { ...(liveOutcomes.has(slot.view.problem ?? "") ? { problem: null } : {}), transport, live };
|
|
974
|
+
}
|
|
975
|
+
async closeSlot(slot) {
|
|
976
|
+
// Failed adapter/native shutdown keeps the original adapter/scope and leases
|
|
977
|
+
// for fail-stop cleanup, but cannot expose a connection or take a ready shortcut.
|
|
978
|
+
slot.usable = false;
|
|
979
|
+
if (slot.timer !== null)
|
|
980
|
+
clearTimeout(slot.timer);
|
|
981
|
+
slot.timer = null;
|
|
982
|
+
const stopAssessment = slot.stopAssessment;
|
|
983
|
+
slot.stopAssessment = null;
|
|
984
|
+
try {
|
|
985
|
+
stopAssessment?.();
|
|
986
|
+
}
|
|
987
|
+
catch { /* observer must not prevent native/lease cleanup */ }
|
|
988
|
+
slot.lifetime?.abort();
|
|
989
|
+
await slot.selected?.close();
|
|
990
|
+
slot.selected = null;
|
|
991
|
+
slot.scope = null;
|
|
992
|
+
slot.lifetime = null;
|
|
993
|
+
await slot.host?.close();
|
|
994
|
+
slot.host = null;
|
|
995
|
+
await slot.lease?.release();
|
|
996
|
+
slot.lease = null;
|
|
997
|
+
slot.leaseScope = null;
|
|
998
|
+
}
|
|
999
|
+
/** Close every open collection, in order; the first failure stops (quarantined). */
|
|
1000
|
+
async closeSlots() {
|
|
1001
|
+
for (const slot of [...this.slots.values()]) {
|
|
1002
|
+
await this.closeSlot(slot);
|
|
1003
|
+
this.deleteSlot(slot);
|
|
1004
|
+
}
|
|
1005
|
+
const host = this.host;
|
|
1006
|
+
this.host = null;
|
|
1007
|
+
await host?.close();
|
|
1008
|
+
}
|
|
1009
|
+
clearSelection() {
|
|
1010
|
+
return this.operation(async () => { await this.closeSlots(); this.focus = null; this.publish({ status: "unselected", problem: null }); return this.getSnapshot(); });
|
|
1011
|
+
}
|
|
1012
|
+
/** SDK-2: re-read the approved collection list (the app is shown or focused
|
|
1013
|
+
* again). Only a settled paired session; a busy session answers with the
|
|
1014
|
+
* current view. The open collection stays open; a failed read changes nothing. */
|
|
1015
|
+
refreshCollectionList() {
|
|
1016
|
+
if (this.pending || !this.flow || !this.installation || this.consentPending || this.flow.view().state !== "paired"
|
|
1017
|
+
|| this.base.status !== "unselected")
|
|
1018
|
+
return Promise.resolve(this.getSnapshot());
|
|
1019
|
+
return this.operation(async () => { await this.refreshCollections(); return this.getSnapshot(); }, true);
|
|
1020
|
+
}
|
|
1021
|
+
/** Accepted COMPLETE inventory omission or terminal native/log refusal only.
|
|
1022
|
+
* Local Forget, failed GETs and transient transport failures do not qualify. */
|
|
1023
|
+
scopeWasRemoved(collectionId) { return this.removedScopes.has(collectionId); }
|
|
1024
|
+
removedScopeIds() { return Object.freeze([...this.removedScopes]); }
|
|
1025
|
+
/** Explicit hosted/browser gesture permission, not a diagnostic-code test.
|
|
1026
|
+
* No native owner, keys or collection adapter may have started in this slot. */
|
|
1027
|
+
canAbandonWrongAccount() {
|
|
1028
|
+
return !this.closing && !this.options.signal.aborted && this.pending === null && this.flow?.canAbandonWrongAccount() === true &&
|
|
1029
|
+
this.installation === null && this.host === null && this.slots.size === 0 && !this.attested && !this.acknowledged;
|
|
1030
|
+
}
|
|
1031
|
+
/** SDK composition metadata only. Protected references never loan the
|
|
1032
|
+
* original credential/keys or carry consent into a fresh installation. */
|
|
1033
|
+
scopeRecoveryContext() {
|
|
1034
|
+
if (!this.flow || !this.installation || this.flow.view().state !== "paired")
|
|
1035
|
+
return null;
|
|
1036
|
+
const view = this.flow.view();
|
|
1037
|
+
return Object.freeze({ accountId: this.installation.scope.account, accountLabel: view.accountEmail ?? (view.accountLogin ? `@${view.accountLogin}` : null), references: this.flow.collectionRecoveries() });
|
|
1038
|
+
}
|
|
1039
|
+
/** Explicit recovery gesture, after terminal access removal. Stop/fence and
|
|
1040
|
+
* erase ONLY the old collection scope before allocating its fresh local slot.
|
|
1041
|
+
* A failed stop/erase refuses recovery rather than releasing old authority. */
|
|
1042
|
+
prepareScopedRecovery(collectionId, expectedReplacement) {
|
|
1043
|
+
this.check();
|
|
1044
|
+
if (this.pending)
|
|
1045
|
+
return this.pending.catch(() => { }).then(() => this.prepareScopedRecovery(collectionId, expectedReplacement));
|
|
1046
|
+
return this.operation(async () => {
|
|
1047
|
+
if (!this.flow || !this.installation || this.consentPending || this.flow.view().state !== "paired" || !this.flow.view().collectionIds.includes(collectionId))
|
|
1048
|
+
throw failure("binding");
|
|
1049
|
+
const refs = this.flow.collectionRecoveries(), slot = this.slots.get(collectionId);
|
|
1050
|
+
if (expectedReplacement === undefined && !Object.hasOwn(refs, collectionId) && !this.scopeWasRemoved(collectionId))
|
|
1051
|
+
throw failure("binding");
|
|
1052
|
+
if (slot) {
|
|
1053
|
+
await this.closeSlot(slot);
|
|
1054
|
+
this.check();
|
|
1055
|
+
this.deleteSlot(slot);
|
|
1056
|
+
}
|
|
1057
|
+
await this.flow.retireCollectionScope(this.installation, collectionId, expectedReplacement ?? null);
|
|
1058
|
+
this.check();
|
|
1059
|
+
const selected = this.flow.confirmedSelection(), p = this.options;
|
|
1060
|
+
if (!await eraseAppCollectionAccess({ cpOrigin: p.cpOrigin, appId: p.appId, accountId: selected.accountId, connectorId: selected.connectorId,
|
|
1061
|
+
installationId: selected.installationId, deviceId: selected.deviceId, collectionIds: [collectionId], databases: [] }, collectionId))
|
|
1062
|
+
throw failure("recovery_required");
|
|
1063
|
+
this.check();
|
|
1064
|
+
const reference = await this.flow.freshCollectionInstallation(this.installation, collectionId);
|
|
1065
|
+
this.check();
|
|
1066
|
+
return Object.freeze({ accountId: selected.accountId, reference });
|
|
1067
|
+
}, true);
|
|
1068
|
+
}
|
|
1069
|
+
/** Forget only local presentation/selection, never revoke CP consent, delete
|
|
1070
|
+
* collection data or erase original protected installation/custody storage. */
|
|
1071
|
+
forget(collectionId) {
|
|
1072
|
+
return this.operation(async () => {
|
|
1073
|
+
const slot = this.slots.get(collectionId);
|
|
1074
|
+
if (slot) {
|
|
1075
|
+
await this.closeSlot(slot);
|
|
1076
|
+
this.check();
|
|
1077
|
+
this.deleteSlot(slot);
|
|
1078
|
+
}
|
|
1079
|
+
this.forgotten.add(collectionId);
|
|
1080
|
+
this.publish({ collections: Object.freeze(this.base.collections.filter(c => c.collectionId !== collectionId)) });
|
|
1081
|
+
return this.getSnapshot();
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
/** Owner-only soft delete of a listed collection, for everyone. A refusal
|
|
1085
|
+
* never blocks the session; it rejects with a bounded delete code and
|
|
1086
|
+
* leaves the collection open. On success the caller forgets it locally. */
|
|
1087
|
+
deleteCollection(collectionId, confirmName) {
|
|
1088
|
+
let refusal = null;
|
|
1089
|
+
return this.operation(async () => {
|
|
1090
|
+
const entry = this.base.collections.find(c => c.collectionId === collectionId);
|
|
1091
|
+
if (!this.flow || !this.installation || !entry)
|
|
1092
|
+
refusal = new AppCollectionDeleteError("collection_delete_not_found");
|
|
1093
|
+
else if (entry.role !== "owner")
|
|
1094
|
+
refusal = new AppCollectionDeleteError("collection_delete_not_owner");
|
|
1095
|
+
else {
|
|
1096
|
+
try {
|
|
1097
|
+
await this.flow.deleteApprovedCollection(this.installation, collectionId, confirmName);
|
|
1098
|
+
}
|
|
1099
|
+
catch (error) {
|
|
1100
|
+
refusal = collectionDeleteError(error);
|
|
1101
|
+
}
|
|
1102
|
+
this.check();
|
|
1103
|
+
}
|
|
1104
|
+
return this.getSnapshot();
|
|
1105
|
+
}).then(snapshot => { if (refusal)
|
|
1106
|
+
throw refusal; return snapshot; });
|
|
1107
|
+
}
|
|
1108
|
+
/** UX-011: end the server session and erase this browser's sign-in data,
|
|
1109
|
+
* keys and cached collections for this installation. Afterwards start()
|
|
1110
|
+
* finds no installation (signed_out) and authorize() begins a fresh pairing.
|
|
1111
|
+
* Pending-write checks belong to the page owner of the connection.
|
|
1112
|
+
*
|
|
1113
|
+
* Order: close the open collection (adapter, native host, lease), attempt
|
|
1114
|
+
* the server sign-out, close the flow (and its ledger connection) and leases,
|
|
1115
|
+
* THEN erase. A failed server sign-out (offline, 5xx, any refusal other than
|
|
1116
|
+
* "already signed out") still erases local state: a person who signs out
|
|
1117
|
+
* must not stay signed in on this device because the network failed. It is
|
|
1118
|
+
* reported in `signOutResult.server` as a diagnostic, not a problem. Only a
|
|
1119
|
+
* failure to remove the installation ledger itself (a reload would restore
|
|
1120
|
+
* the session) or to stop the open collection is `sign_out_failed`. */
|
|
1121
|
+
signOut() {
|
|
1122
|
+
this.check();
|
|
1123
|
+
// A background approval poll holds the slot: let it settle first.
|
|
1124
|
+
const poll = this.pending !== null && this.pending === this.polling ? this.pending : null;
|
|
1125
|
+
return Promise.resolve(poll?.catch(() => { })).then(() => this.operation(async () => {
|
|
1126
|
+
const flow = this.flow;
|
|
1127
|
+
let view = null, connectorId = null, webPush = false;
|
|
1128
|
+
try {
|
|
1129
|
+
view = flow?.view() ?? null;
|
|
1130
|
+
}
|
|
1131
|
+
catch {
|
|
1132
|
+
view = null;
|
|
1133
|
+
}
|
|
1134
|
+
try {
|
|
1135
|
+
connectorId = flow?.confirmedSelection().connectorId ?? null;
|
|
1136
|
+
}
|
|
1137
|
+
catch {
|
|
1138
|
+
connectorId = null;
|
|
1139
|
+
}
|
|
1140
|
+
try {
|
|
1141
|
+
webPush = flow?.hasWebPushChannel() === true;
|
|
1142
|
+
}
|
|
1143
|
+
catch {
|
|
1144
|
+
webPush = false;
|
|
1145
|
+
}
|
|
1146
|
+
const collectionIds = [...new Set([...(view?.collectionIds ?? []), ...this.base.collections.map(c => c.collectionId)])];
|
|
1147
|
+
this.closeApprovalWindow();
|
|
1148
|
+
this.fileAccess = null;
|
|
1149
|
+
this.consentPending = false;
|
|
1150
|
+
try {
|
|
1151
|
+
await this.closeSlots();
|
|
1152
|
+
}
|
|
1153
|
+
catch (error) {
|
|
1154
|
+
this.failSignOut();
|
|
1155
|
+
throw error;
|
|
1156
|
+
}
|
|
1157
|
+
this.check();
|
|
1158
|
+
let server = "not_paired";
|
|
1159
|
+
if (flow && view?.state === "paired") {
|
|
1160
|
+
try {
|
|
1161
|
+
server = await flow.signOutInstallation();
|
|
1162
|
+
}
|
|
1163
|
+
catch {
|
|
1164
|
+
server = "incomplete";
|
|
1165
|
+
}
|
|
1166
|
+
this.check();
|
|
1167
|
+
}
|
|
1168
|
+
// Close every connection to this installation's stores before deleting them.
|
|
1169
|
+
this.flow = null;
|
|
1170
|
+
this.installation = null;
|
|
1171
|
+
try {
|
|
1172
|
+
await flow?.close();
|
|
1173
|
+
}
|
|
1174
|
+
catch { /* the ledger handle closes on versionchange anyway */ }
|
|
1175
|
+
this.flowLifetime.abort();
|
|
1176
|
+
this.flowLifetime = new AbortController();
|
|
1177
|
+
await this.installationLease?.release();
|
|
1178
|
+
this.installationLease = null;
|
|
1179
|
+
this.attested = false;
|
|
1180
|
+
this.acknowledged = false;
|
|
1181
|
+
this.freshApproval = false;
|
|
1182
|
+
this.authorizationStartedAt = null;
|
|
1183
|
+
this.receiptRead = null;
|
|
1184
|
+
this.foregroundRead = null;
|
|
1185
|
+
this.forgotten.clear();
|
|
1186
|
+
this.removedScopes.clear();
|
|
1187
|
+
const p = this.options;
|
|
1188
|
+
const local = await eraseAppInstallationData({ cpOrigin: p.cpOrigin, appId: p.appId, ...(p.owner === undefined ? {} : { owner: p.owner }),
|
|
1189
|
+
...(p.storageNamespace === undefined ? {} : { storageNamespace: p.storageNamespace }),
|
|
1190
|
+
accountId: view?.accountId ?? null, connectorId, installationId: view?.installationId ?? null, deviceId: view?.deviceId ?? null,
|
|
1191
|
+
collectionIds, databases: p.localDatabases ?? [], ...(p.recoveryFor ? { isolated: true } : {}) });
|
|
1192
|
+
this.check();
|
|
1193
|
+
if (!local.ledger) {
|
|
1194
|
+
this.failSignOut();
|
|
1195
|
+
throw mdbaseError("unavailable", "This device couldn't remove its sign-in data.", "sign_out_failed");
|
|
1196
|
+
}
|
|
1197
|
+
this.emit(Object.freeze({ status: "signed_out", signIn: null, collections: Object.freeze([]), selectedCollectionId: null, problem: null, timing: null,
|
|
1198
|
+
signOutResult: Object.freeze({ server, local: local.complete ? "erased" : "incomplete", webPush }) }));
|
|
1199
|
+
return this.getSnapshot();
|
|
1200
|
+
}, true));
|
|
1201
|
+
}
|
|
1202
|
+
failSignOut() {
|
|
1203
|
+
if (this.closing || this.options.signal.aborted)
|
|
1204
|
+
return;
|
|
1205
|
+
let signIn = null;
|
|
1206
|
+
try {
|
|
1207
|
+
signIn = this.flow?.view() ?? null;
|
|
1208
|
+
}
|
|
1209
|
+
catch {
|
|
1210
|
+
signIn = null;
|
|
1211
|
+
}
|
|
1212
|
+
const { problemDetail: _stale, ...previous } = this.base;
|
|
1213
|
+
this.focus = null;
|
|
1214
|
+
this.emit(Object.freeze({ ...previous, status: "blocked", signIn, selectedCollectionId: null, problem: "sign_out_failed" }));
|
|
1215
|
+
}
|
|
1216
|
+
emit(snapshot) {
|
|
1217
|
+
this.check();
|
|
1218
|
+
this.base = snapshot;
|
|
1219
|
+
// Signed out: no collection is held (a failed stop keeps its slot quarantined).
|
|
1220
|
+
if (snapshot.status === "signed_out") {
|
|
1221
|
+
for (const slot of [...this.slots.values()])
|
|
1222
|
+
this.deleteSlot(slot);
|
|
1223
|
+
this.focus = null;
|
|
1224
|
+
}
|
|
1225
|
+
this.changed();
|
|
1226
|
+
}
|
|
1227
|
+
close() {
|
|
1228
|
+
if (this.closing)
|
|
1229
|
+
return this.closing;
|
|
1230
|
+
const pending = this.pending;
|
|
1231
|
+
this.foregroundRead = null;
|
|
1232
|
+
this.stopPolling();
|
|
1233
|
+
this.options.signal.removeEventListener("abort", this.onAbort);
|
|
1234
|
+
this.closing = Promise.resolve().then(async () => {
|
|
1235
|
+
await pending?.catch(() => { });
|
|
1236
|
+
await this.closeSlots();
|
|
1237
|
+
this.focus = null;
|
|
1238
|
+
await this.flow?.close();
|
|
1239
|
+
this.flowLifetime.abort();
|
|
1240
|
+
this.flow = null;
|
|
1241
|
+
this.installation = null;
|
|
1242
|
+
await this.installationLease?.release();
|
|
1243
|
+
this.installationLease = null;
|
|
1244
|
+
this.base = Object.freeze({ status: "closed", signIn: null, collections: Object.freeze([]), selectedCollectionId: null, problem: null, timing: this.base.timing });
|
|
1245
|
+
this.snapshotValue = this.base;
|
|
1246
|
+
for (const listener of [...this.listeners]) {
|
|
1247
|
+
try {
|
|
1248
|
+
listener();
|
|
1249
|
+
}
|
|
1250
|
+
catch { /* close remains fail-stop */ }
|
|
1251
|
+
}
|
|
1252
|
+
this.listeners.clear();
|
|
1253
|
+
});
|
|
1254
|
+
this.lifetime.abort();
|
|
1255
|
+
return this.closing;
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
//# sourceMappingURL=web-sign-in-session.js.map
|