chore: designated survivor test suite (#2540)

* chore: designated survivor test suite

* add more tests

* fix: tests exclusivness

* fix removing account from shared vaults test
This commit is contained in:
Karol Sójko
2023-09-27 14:27:12 +02:00
committed by GitHub
parent 70cc15c6d9
commit 981417f952
17 changed files with 537 additions and 95 deletions

View File

@@ -36,7 +36,7 @@
},
"dependencies": {
"@standardnotes/common": "^1.50.0",
"@standardnotes/domain-core": "^1.33.1",
"@standardnotes/domain-core": "^1.34.1",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "workspace:*",
"@standardnotes/utils": "workspace:*",

View File

@@ -35,7 +35,7 @@
},
"dependencies": {
"@electron/remote": "^2.0.9",
"@standardnotes/domain-core": "^1.33.1",
"@standardnotes/domain-core": "^1.34.1",
"@standardnotes/electron-clear-data": "1.1.1",
"@standardnotes/web": "workspace:*",
"axios": "^1.1.3",

View File

@@ -29,7 +29,7 @@
},
"dependencies": {
"@standardnotes/common": "^1.50.0",
"@standardnotes/domain-core": "^1.33.1",
"@standardnotes/domain-core": "^1.34.1",
"@standardnotes/models": "workspace:*",
"@standardnotes/responses": "workspace:*",
"@standardnotes/sncrypto-common": "workspace:*",

View File

@@ -26,7 +26,7 @@
},
"dependencies": {
"@standardnotes/common": "^1.50.0",
"@standardnotes/domain-core": "^1.33.1",
"@standardnotes/domain-core": "^1.34.1",
"reflect-metadata": "^0.1.13"
},
"devDependencies": {

View File

@@ -20,7 +20,7 @@
},
"dependencies": {
"@standardnotes/common": "^1.50.0",
"@standardnotes/domain-core": "^1.33.1",
"@standardnotes/domain-core": "^1.34.1",
"@standardnotes/features": "workspace:*",
"@standardnotes/responses": "workspace:*",
"@standardnotes/sncrypto-common": "workspace:^",

View File

@@ -18,7 +18,7 @@
"dependencies": {
"@standardnotes/api": "workspace:^",
"@standardnotes/common": "^1.50.0",
"@standardnotes/domain-core": "^1.33.1",
"@standardnotes/domain-core": "^1.34.1",
"@standardnotes/encryption": "workspace:^",
"@standardnotes/features": "workspace:^",
"@standardnotes/files": "workspace:^",

View File

@@ -96,7 +96,7 @@ export class SharedVaultService
await this.handleNotification(event.payload as NotificationServiceEventPayload)
break
case SyncEvent.ReceivedRemoteSharedVaults:
void this.notifyEventSync(SharedVaultServiceEvent.SharedVaultStatusChanged)
void this.notifyEvent(SharedVaultServiceEvent.SharedVaultStatusChanged)
break
}
}
@@ -113,7 +113,20 @@ export class SharedVaultService
break
}
case NotificationType.TYPES.UserRemovedFromSharedVault: {
this.vaultUsers.invalidateVaultUsersCache(event.eventPayload.props.primaryIdentifier.value).catch(console.error)
const vaultOrError = this._getVault.execute<SharedVaultListingInterface>({
sharedVaultUuid: event.eventPayload.props.primaryIdentifier.value,
})
if (!vaultOrError.isFailed()) {
const vault = vaultOrError.getValue()
this.vaultUsers
.invalidateVaultUsersCache(event.eventPayload.props.primaryIdentifier.value)
.catch(console.error)
await this._syncLocalVaultsWithRemoteSharedVaults.execute([vault])
void this.notifyEvent(SharedVaultServiceEvent.SharedVaultStatusChanged)
}
break
}
case NotificationType.TYPES.SharedVaultItemRemoved: {
@@ -124,14 +137,15 @@ export class SharedVaultService
break
}
case NotificationType.TYPES.SharedVaultFileRemoved:
case NotificationType.TYPES.SharedVaultFileUploaded: {
case NotificationType.TYPES.SharedVaultFileUploaded:
case NotificationType.TYPES.UserDesignatedAsSurvivor: {
const vaultOrError = this._getVault.execute<SharedVaultListingInterface>({
sharedVaultUuid: event.eventPayload.props.primaryIdentifier.value,
})
if (!vaultOrError.isFailed()) {
await this._syncLocalVaultsWithRemoteSharedVaults.execute([vaultOrError.getValue()])
void this.notifyEventSync(SharedVaultServiceEvent.SharedVaultStatusChanged)
void this.notifyEvent(SharedVaultServiceEvent.SharedVaultStatusChanged)
}
break

View File

@@ -1,4 +1,7 @@
export const BaseTests = [
export const BaseTests = {
enabled: true,
exclusive: false,
files: [
'memory.test.js',
'protocol.test.js',
'utils.test.js',
@@ -57,3 +60,4 @@ export const BaseTests = [
'subscriptions.test.js',
'recovery.test.js',
]
}

View File

@@ -23,5 +23,6 @@ export const VaultTests = {
'vaults/files.test.js',
'vaults/limits.test.js',
'vaults/quota.test.js',
'vaults/surviving.test.js',
],
}

View File

@@ -41,7 +41,7 @@ export const acceptAllInvites = async (context) => {
}
}
const inviteContext = async (context, contactContext, sharedVault, contact, permission) => {
export const inviteContext = async (context, contactContext, sharedVault, contact, permission) => {
contactContext.lockSyncing()
const inviteOrError = await context.vaultInvites.inviteContactToSharedVault(sharedVault, contact, permission)
@@ -207,3 +207,12 @@ export const moveItemToVault = async (context, sharedVault, item) => {
return result.getValue()
}
export const designateSharedVaultSurvior = async (context, sharedVault, survivorUuid) => {
const result = await context.vaultUsers.designateSurvivor(sharedVault, survivorUuid)
if (result.isFailed()) {
throw new Error(result.getError())
}
return result.getValue()
}

View File

@@ -38,6 +38,14 @@
<script type="module">
import MainRegistry from './TestRegistry/MainRegistry.js'
const urlSearchParams = new URLSearchParams(window.location.search);
const testSuite = urlSearchParams.get('suite');
if (testSuite === 'vaults') {
MainRegistry.VaultTests.exclusive = true;
} else if (testSuite === 'base') {
MainRegistry.BaseTests.exclusive = true;
}
const loadTest = (fileName) => {
return new Promise((resolve) => {
const script = document.createElement('script');
@@ -56,19 +64,18 @@
}
}
if (MainRegistry.VaultTests.enabled) {
InternalFeatureService.get().enableFeature(InternalFeature.Vaults);
if (MainRegistry.VaultTests.exclusive) {
await loadTests(MainRegistry.VaultTests.files);
} else if (MainRegistry.BaseTests.exclusive) {
await loadTests(MainRegistry.BaseTests.files);
} else {
await loadTests([
...MainRegistry.BaseTests,
...MainRegistry.BaseTests.files,
...MainRegistry.VaultTests.files
]);
}
} else {
await loadTests(MainRegistry.BaseTests);
}
mocha.run()
</script>

View File

@@ -1,4 +1,5 @@
import * as Factory from '../lib/factory.js'
import * as Utils from '../lib/Utils.js'
import * as Collaboration from '../lib/Collaboration.js'
chai.use(chaiAsPromised)
@@ -167,4 +168,47 @@ describe('shared vault deletion', function () {
await deinitContactContext()
})
it('should remove a user from all shared vaults upon account removal', async () => {
const secondContext = await Factory.createVaultsContextWithRealCrypto()
await secondContext.launch()
await secondContext.register()
const thirdContext = await Factory.createVaultsContextWithRealCrypto()
await thirdContext.launch()
await thirdContext.register()
const firstVault = await Collaboration.createSharedVault(context)
const secondVault = await Collaboration.createSharedVault(thirdContext)
const firstToSecondContact = await Collaboration.createTrustedContactForUserOfContext(context, secondContext)
await Collaboration.createTrustedContactForUserOfContext(secondContext, context)
const thirdToSecondContact = await Collaboration.createTrustedContactForUserOfContext(thirdContext, secondContext)
await Collaboration.createTrustedContactForUserOfContext(thirdContext, context)
await Collaboration.inviteContext(context, secondContext, firstVault, firstToSecondContact, SharedVaultUserPermission.PERMISSIONS.Write)
await Collaboration.inviteContext(thirdContext, secondContext, secondVault, thirdToSecondContact, SharedVaultUserPermission.PERMISSIONS.Write)
const promise = secondContext.awaitNextSyncSharedVaultFromScratchEvent()
await Collaboration.acceptAllInvites(secondContext)
await Utils.awaitPromiseOrThrow(promise, 2.0, 'Waiting for vault to sync')
Factory.handlePasswordChallenges(secondContext.application, secondContext.password)
await secondContext.application.user.deleteAccount()
await context.syncAndAwaitNotificationsProcessing()
await thirdContext.syncAndAwaitNotificationsProcessing()
const sharedVaultUsersInFirstVault = await context.vaultUsers.getSharedVaultUsersFromServer(firstVault)
expect(sharedVaultUsersInFirstVault.length).to.equal(1)
const sharedVaultUsersInSecondVault = await thirdContext.vaultUsers.getSharedVaultUsersFromServer(secondVault)
expect(sharedVaultUsersInSecondVault.length).to.equal(1)
await secondContext.deinit()
await thirdContext.deinit()
})
})

View File

@@ -0,0 +1,363 @@
import * as Factory from '../lib/factory.js'
import * as Files from '../lib/Files.js'
import * as Collaboration from '../lib/Collaboration.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe('designated survival', function () {
this.timeout(Factory.TwentySecondTimeout)
let context
let secondContext
let thirdContext
beforeEach(async function () {
localStorage.clear()
context = await Factory.createVaultsContextWithRealCrypto()
await context.launch()
await context.register()
})
afterEach(async function () {
await context.deinit()
localStorage.clear()
sinon.restore()
context = undefined
if (secondContext) {
await secondContext.deinit()
secondContext = undefined
}
if (thirdContext) {
await thirdContext.deinit()
thirdContext = undefined
}
})
it('should indicate that a vault has a designated survivor', async () => {
const { sharedVault, contactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
secondContext = contactContext
let vault = context.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })
expect(vault.sharing.designatedSurvivor).to.be.null
await Collaboration.designateSharedVaultSurvior(context, sharedVault, contactContext.userUuid)
await context.syncAndAwaitNotificationsProcessing()
vault = context.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })
expect(vault.sharing.designatedSurvivor).to.equal(contactContext.userUuid)
})
describe('owner of a shared vault with a designated survivor removing the vault', () => {
it('should not remove all users from the vault upon shared vault removal', async () => {
const { sharedVault, contactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
secondContext = contactContext
await Collaboration.designateSharedVaultSurvior(context, sharedVault, contactContext.userUuid)
const { thirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
context,
sharedVault,
)
thirdContext = thirdPartyContext
await Collaboration.acceptAllInvites(thirdContext)
await context.sharedVaults.deleteSharedVault(sharedVault)
await context.syncAndAwaitNotificationsProcessing()
await secondContext.syncAndAwaitNotificationsProcessing()
await thirdContext.syncAndAwaitNotificationsProcessing()
const sharedVaultUsers = await secondContext.vaultUsers.getSharedVaultUsersFromServer(sharedVault)
expect(sharedVaultUsers.length).to.equal(2)
expect(context.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })).to.be.undefined
expect(context.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.be.undefined
expect(context.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.be.empty
expect(secondContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })).to.not.be.undefined
expect(secondContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.not.be.undefined
expect(secondContext.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.not.be.empty
expect(thirdContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })).to.not.be.undefined
expect(thirdContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.not.be.undefined
expect(thirdContext.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.not.be.empty
})
it('should transition items of the owner in the vault to the designated survivor', async () => {
const { sharedVault, contactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
secondContext = contactContext
await Collaboration.designateSharedVaultSurvior(context, sharedVault, contactContext.userUuid)
const { thirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
context,
sharedVault,
)
thirdContext = thirdPartyContext
await Collaboration.acceptAllInvites(thirdContext)
const note = await context.createSyncedNote('foo', 'bar')
await Collaboration.moveItemToVault(context, sharedVault, note)
await context.sharedVaults.deleteSharedVault(sharedVault)
await secondContext.syncAndAwaitNotificationsProcessing()
await thirdContext.syncAndAwaitNotificationsProcessing()
const sharedVaultUsers = await secondContext.vaultUsers.getSharedVaultUsersFromServer(sharedVault)
expect(sharedVaultUsers.length).to.equal(2)
const contactNote = secondContext.items.findItem(note.uuid)
expect(contactNote.key_system_identifier).to.equal(sharedVault.systemIdentifier)
expect(contactNote.user_uuid).to.equal(secondContext.userUuid)
const thirdPartyNote = thirdContext.items.findItem(note.uuid)
expect(thirdPartyNote.key_system_identifier).to.equal(sharedVault.systemIdentifier)
expect(thirdPartyNote.user_uuid).to.equal(secondContext.userUuid)
})
it('should still allow to download files of the owner in the vault', async () => {
await context.activatePaidSubscriptionForUser()
const { sharedVault, contactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
secondContext = contactContext
await Collaboration.designateSharedVaultSurvior(context, sharedVault, contactContext.userUuid)
const { thirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
context,
sharedVault,
)
thirdContext = thirdPartyContext
await Collaboration.acceptAllInvites(thirdContext)
const response = await fetch('/mocha/assets/small_file.md')
const buffer = new Uint8Array(await response.arrayBuffer())
const uploadedFile = await Files.uploadFile(context.files, buffer, 'my-file', 'md', 1000, sharedVault)
await secondContext.syncAndAwaitNotificationsProcessing()
const sharedFileBefore = secondContext.items.findItem(uploadedFile.uuid)
expect(sharedFileBefore).to.not.be.undefined
expect(sharedFileBefore.remoteIdentifier).to.equal(uploadedFile.remoteIdentifier)
await context.sharedVaults.deleteSharedVault(sharedVault)
await secondContext.syncAndAwaitNotificationsProcessing()
const sharedFileAfter = secondContext.items.findItem(uploadedFile.uuid)
expect(sharedFileAfter).to.not.be.undefined
expect(sharedFileAfter.remoteIdentifier).to.equal(uploadedFile.remoteIdentifier)
const downloadedBytes = await Files.downloadFile(secondContext.files, sharedFileAfter)
expect(downloadedBytes).to.eql(buffer)
})
it('should transition vault ownership to the designated survivor', async () => {
const { sharedVault, contactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
secondContext = contactContext
await Collaboration.designateSharedVaultSurvior(context, sharedVault, contactContext.userUuid)
const { thirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
context,
sharedVault,
)
thirdContext = thirdPartyContext
await Collaboration.acceptAllInvites(thirdContext)
await context.sharedVaults.deleteSharedVault(sharedVault)
await secondContext.syncAndAwaitNotificationsProcessing()
await thirdContext.syncAndAwaitNotificationsProcessing()
const contactVault = secondContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })
expect(contactVault.sharing.ownerUserUuid).to.not.equal(context.userUuid)
expect(contactVault.sharing.ownerUserUuid).to.equal(secondContext.userUuid)
const thirdPartyVault = thirdContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })
expect(thirdPartyVault.sharing.ownerUserUuid).to.not.equal(context.userUuid)
expect(thirdPartyVault.sharing.ownerUserUuid).to.equal(secondContext.userUuid)
})
})
describe('owner of a shared vault with a designated survivor deleting their account', () => {
it('should not remove all users from the vault upon account removal', async () => {
const { sharedVault, contactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
secondContext = contactContext
await Collaboration.designateSharedVaultSurvior(context, sharedVault, contactContext.userUuid)
const { thirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
context,
sharedVault,
)
thirdContext = thirdPartyContext
await Collaboration.acceptAllInvites(thirdContext)
Factory.handlePasswordChallenges(context.application, context.password)
await context.application.user.deleteAccount()
await secondContext.syncAndAwaitNotificationsProcessing()
await thirdContext.syncAndAwaitNotificationsProcessing()
const sharedVaultUsers = await secondContext.vaultUsers.getSharedVaultUsersFromServer(sharedVault)
expect(sharedVaultUsers.length).to.equal(2)
expect(secondContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })).to.not.be.undefined
expect(secondContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.not.be.undefined
expect(secondContext.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.not.be.empty
expect(thirdContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })).to.not.be.undefined
expect(thirdContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.not.be.undefined
expect(thirdContext.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.not.be.empty
})
it('should transition items of the owner in the vault to the designated survivor', async () => {
const { sharedVault, contactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
secondContext = contactContext
await Collaboration.designateSharedVaultSurvior(context, sharedVault, contactContext.userUuid)
const { thirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
context,
sharedVault,
)
thirdContext = thirdPartyContext
await Collaboration.acceptAllInvites(thirdContext)
const note = await context.createSyncedNote('foo', 'bar')
await Collaboration.moveItemToVault(context, sharedVault, note)
Factory.handlePasswordChallenges(context.application, context.password)
await context.application.user.deleteAccount()
await secondContext.syncAndAwaitNotificationsProcessing()
await thirdContext.syncAndAwaitNotificationsProcessing()
const sharedVaultUsers = await secondContext.vaultUsers.getSharedVaultUsersFromServer(sharedVault)
expect(sharedVaultUsers.length).to.equal(2)
const contactNote = secondContext.items.findItem(note.uuid)
expect(contactNote.key_system_identifier).to.equal(sharedVault.systemIdentifier)
expect(contactNote.user_uuid).to.equal(secondContext.userUuid)
const thirdPartyNote = thirdContext.items.findItem(note.uuid)
expect(thirdPartyNote.key_system_identifier).to.equal(sharedVault.systemIdentifier)
expect(thirdPartyNote.user_uuid).to.equal(secondContext.userUuid)
})
it('should still allow to download files of the owner in the vault', async () => {
await context.activatePaidSubscriptionForUser()
const { sharedVault, contactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
secondContext = contactContext
await Collaboration.designateSharedVaultSurvior(context, sharedVault, contactContext.userUuid)
const { thirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
context,
sharedVault,
)
thirdContext = thirdPartyContext
await Collaboration.acceptAllInvites(thirdContext)
const response = await fetch('/mocha/assets/small_file.md')
const buffer = new Uint8Array(await response.arrayBuffer())
const uploadedFile = await Files.uploadFile(context.files, buffer, 'my-file', 'md', 1000, sharedVault)
await secondContext.syncAndAwaitNotificationsProcessing()
const sharedFileBefore = secondContext.items.findItem(uploadedFile.uuid)
expect(sharedFileBefore).to.not.be.undefined
expect(sharedFileBefore.remoteIdentifier).to.equal(uploadedFile.remoteIdentifier)
Factory.handlePasswordChallenges(context.application, context.password)
await context.application.user.deleteAccount()
await secondContext.syncAndAwaitNotificationsProcessing()
const sharedFileAfter = secondContext.items.findItem(uploadedFile.uuid)
expect(sharedFileAfter).to.not.be.undefined
expect(sharedFileAfter.remoteIdentifier).to.equal(uploadedFile.remoteIdentifier)
const downloadedBytes = await Files.downloadFile(secondContext.files, sharedFileAfter)
expect(downloadedBytes).to.eql(buffer)
})
it('should transition vault ownership to the designated survivor', async () => {
const { sharedVault, contactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
secondContext = contactContext
await Collaboration.designateSharedVaultSurvior(context, sharedVault, contactContext.userUuid)
const { thirdPartyContext } = await Collaboration.inviteNewPartyToSharedVault(
context,
sharedVault,
)
thirdContext = thirdPartyContext
await Collaboration.acceptAllInvites(thirdContext)
Factory.handlePasswordChallenges(context.application, context.password)
await context.application.user.deleteAccount()
await secondContext.syncAndAwaitNotificationsProcessing()
await thirdContext.syncAndAwaitNotificationsProcessing()
const contactVault = secondContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })
expect(contactVault.sharing.ownerUserUuid).to.equal(secondContext.userUuid)
const thirdPartyVault = thirdContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })
expect(thirdPartyVault.sharing.ownerUserUuid).to.equal(secondContext.userUuid)
})
})
describe('owner of a shared vault without a designated survivor deleting their account', () => {
it('should remove all users from all shared vaults upon account removal', async () => {
await context.activatePaidSubscriptionForUser()
const { sharedVault, contactContext } =
await Collaboration.createSharedVaultWithAcceptedInvite(context)
secondContext = contactContext
const result = await Collaboration.createSharedVaultWithAcceptedInvite(context)
thirdContext = result.contactContext
const secondSharedVault = result.sharedVault
Factory.handlePasswordChallenges(context.application, context.password)
await context.application.user.deleteAccount()
await secondContext.syncAndAwaitNotificationsProcessing()
await thirdContext.syncAndAwaitNotificationsProcessing()
expect(secondContext.vaults.getVault({ keySystemIdentifier: sharedVault.systemIdentifier })).to.be.undefined
expect(secondContext.keys.getPrimaryKeySystemRootKey(sharedVault.systemIdentifier)).to.be.undefined
expect(secondContext.keys.getKeySystemItemsKeys(sharedVault.systemIdentifier)).to.be.empty
expect(thirdContext.vaults.getVault({ keySystemIdentifier: secondSharedVault.systemIdentifier })).to.be.undefined
expect(thirdContext.keys.getPrimaryKeySystemRootKey(secondSharedVault.systemIdentifier)).to.be.undefined
expect(thirdContext.keys.getKeySystemItemsKeys(secondSharedVault.systemIdentifier)).to.be.empty
})
})
})

View File

@@ -37,7 +37,7 @@
"@babel/preset-env": "*",
"@standardnotes/api": "workspace:*",
"@standardnotes/common": "^1.50.0",
"@standardnotes/domain-core": "^1.33.1",
"@standardnotes/domain-core": "^1.34.1",
"@standardnotes/domain-events": "^2.122.0",
"@standardnotes/encryption": "workspace:*",
"@standardnotes/features": "workspace:*",

View File

@@ -16,7 +16,7 @@
},
"dependencies": {
"@standardnotes/common": "^1.50.0",
"@standardnotes/domain-core": "^1.33.1",
"@standardnotes/domain-core": "^1.34.1",
"@standardnotes/features": "workspace:^",
"@standardnotes/filepicker": "workspace:^",
"@standardnotes/models": "workspace:^",

View File

@@ -4138,7 +4138,7 @@ __metadata:
resolution: "@standardnotes/api@workspace:packages/api"
dependencies:
"@standardnotes/common": ^1.50.0
"@standardnotes/domain-core": ^1.33.1
"@standardnotes/domain-core": ^1.34.1
"@standardnotes/models": "workspace:*"
"@standardnotes/responses": "workspace:*"
"@standardnotes/utils": "workspace:*"
@@ -4288,7 +4288,7 @@ __metadata:
"@babel/core": "*"
"@babel/preset-env": "*"
"@electron/remote": ^2.0.9
"@standardnotes/domain-core": ^1.33.1
"@standardnotes/domain-core": ^1.34.1
"@standardnotes/electron-clear-data": 1.1.1
"@standardnotes/web": "workspace:*"
"@types/fs-extra": ^11.0.1
@@ -4340,12 +4340,12 @@ __metadata:
languageName: node
linkType: hard
"@standardnotes/domain-core@npm:^1.33.1":
version: 1.33.1
resolution: "@standardnotes/domain-core@npm:1.33.1"
"@standardnotes/domain-core@npm:^1.34.1":
version: 1.34.1
resolution: "@standardnotes/domain-core@npm:1.34.1"
dependencies:
uuid: ^9.0.0
checksum: 4caba6cd6fa667158aa326e43762bc466b726dfbd89e04cfc6fd6b89dce573b1be231350470fc7f1d027868bfd096096de7733256d35a7be699d693e84d29f2a
checksum: 29fa0ee7868b08a5255ce737535aa67b9fe8f0562f7d5a308f4be4a63d46821f34b4ea1d4241064e3025968ae45e09eba3dcbd1ff8d510618114541c42a8e6ae
languageName: node
linkType: hard
@@ -4392,7 +4392,7 @@ __metadata:
dependencies:
"@standardnotes/common": ^1.50.0
"@standardnotes/config": 2.4.3
"@standardnotes/domain-core": ^1.33.1
"@standardnotes/domain-core": ^1.34.1
"@standardnotes/models": "workspace:*"
"@standardnotes/responses": "workspace:*"
"@standardnotes/sncrypto-common": "workspace:*"
@@ -4427,7 +4427,7 @@ __metadata:
resolution: "@standardnotes/features@workspace:packages/features"
dependencies:
"@standardnotes/common": ^1.50.0
"@standardnotes/domain-core": ^1.33.1
"@standardnotes/domain-core": ^1.34.1
"@types/jest": ^29.2.3
"@typescript-eslint/eslint-plugin": "*"
eslint: "*"
@@ -4633,7 +4633,7 @@ __metadata:
resolution: "@standardnotes/models@workspace:packages/models"
dependencies:
"@standardnotes/common": ^1.50.0
"@standardnotes/domain-core": ^1.33.1
"@standardnotes/domain-core": ^1.34.1
"@standardnotes/features": "workspace:*"
"@standardnotes/responses": "workspace:*"
"@standardnotes/sncrypto-common": "workspace:^"
@@ -4729,7 +4729,7 @@ __metadata:
dependencies:
"@standardnotes/api": "workspace:^"
"@standardnotes/common": ^1.50.0
"@standardnotes/domain-core": ^1.33.1
"@standardnotes/domain-core": ^1.34.1
"@standardnotes/encryption": "workspace:^"
"@standardnotes/features": "workspace:^"
"@standardnotes/files": "workspace:^"
@@ -4830,7 +4830,7 @@ __metadata:
"@babel/preset-env": "*"
"@standardnotes/api": "workspace:*"
"@standardnotes/common": ^1.50.0
"@standardnotes/domain-core": ^1.33.1
"@standardnotes/domain-core": ^1.34.1
"@standardnotes/domain-events": ^2.122.0
"@standardnotes/encryption": "workspace:*"
"@standardnotes/features": "workspace:*"
@@ -4955,7 +4955,7 @@ __metadata:
resolution: "@standardnotes/ui-services@workspace:packages/ui-services"
dependencies:
"@standardnotes/common": ^1.50.0
"@standardnotes/domain-core": ^1.33.1
"@standardnotes/domain-core": ^1.34.1
"@standardnotes/features": "workspace:^"
"@standardnotes/filepicker": "workspace:^"
"@standardnotes/models": "workspace:^"