From e61e10d7d75798706b1ac76dd1878ea012703626 Mon Sep 17 00:00:00 2001 From: hhhjin Date: Mon, 28 Sep 2026 11:11:43 +0900 Subject: [PATCH] Add Sync Plus organization vault sharing --- .../0008_sync_access_revocations.sql | 7 + apps/api/drizzle-do/meta/0008_snapshot.json | 526 +++++ apps/api/drizzle-do/meta/_journal.json | 7 + apps/api/drizzle-do/migrations.js | 4 +- apps/api/drizzle/0007_plus_sharing.sql | 73 + apps/api/drizzle/meta/0007_snapshot.json | 1774 +++++++++++++++++ apps/api/drizzle/meta/_journal.json | 7 + apps/api/public/i18n/de.json | 83 +- apps/api/public/i18n/ja.json | 83 +- apps/api/public/i18n/ko.json | 83 +- apps/api/public/i18n/zh-cn.json | 83 +- apps/api/public/i18n/zh-tw.json | 83 +- apps/api/public/invitations.html | 93 + apps/api/public/organization-ui.js | 6 + apps/api/public/organizations.html | 211 ++ apps/api/public/styles.css | 83 + apps/api/public/vault-crypto.js | 2 +- apps/api/public/vaults.html | 55 +- apps/api/src/app.ts | 27 +- .../adapters/inbound/http/error-mapper.ts | 2 + .../adapters/inbound/http/routes.test.ts | 21 +- .../billing/adapters/inbound/http/routes.ts | 23 +- .../outbound/drizzle-billing-store.test.ts | 58 + .../outbound/drizzle-billing-store.ts | 8 +- .../adapters/outbound/polar-provider.test.ts | 89 +- .../adapters/outbound/polar-provider.ts | 67 +- .../billing/adapters/outbound/product-ids.ts | 6 + .../src/billing/application/dto/billing.ts | 1 + .../application/errors/billing-errors.ts | 1 + .../ports/inbound/billing-service.ts | 5 +- .../ports/outbound/billing-provider.ts | 2 + .../services/billing-service.test.ts | 19 + .../application/services/billing-service.ts | 137 +- apps/api/src/billing/domain/policy.ts | 2 +- .../src/composition/create-api-application.ts | 41 +- .../create-coordinator-application.ts | 55 +- .../features/create-auth-feature.ts | 11 +- .../features/create-sync-access-feature.ts | 9 +- .../features/create-vault-feature.ts | 2 + apps/api/src/config/cloudflare.ts | 2 + .../src/db/__tests__/libsql-app-db.test.ts | 2 +- apps/api/src/db/d1/index.ts | 1 + apps/api/src/db/d1/sharing-schema.ts | 72 + apps/api/src/db/d1/vault-schema.ts | 7 +- apps/api/src/db/do/index.ts | 6 + apps/api/src/index.ts | 4 +- apps/api/src/public-pages.test.ts | 2 +- apps/api/src/runtime.ts | 2 +- apps/api/src/runtime/coordinator.ts | 7 +- .../src/runtime/node-coordinator-namespace.ts | 14 +- apps/api/src/runtime/node-coordinator.ts | 51 +- apps/api/src/runtime/node-websocket.ts | 1 + apps/api/src/runtime/node.ts | 8 + apps/api/src/runtime/scheduled.ts | 23 + .../sharing/adapters/drizzle-sharing-store.ts | 618 ++++++ apps/api/src/sharing/adapters/routes.ts | 294 +++ apps/api/src/sharing/application/access.ts | 44 + apps/api/src/sharing/application/refresh.ts | 24 + apps/api/src/sharing/application/service.ts | 532 +++++ apps/api/src/sharing/application/store.ts | 132 ++ apps/api/src/sharing/application/types.ts | 33 + apps/api/src/sharing/migration.test.ts | 65 + apps/api/src/sharing/sharing.test.ts | 488 +++++ apps/api/src/subscription/domain/policy.ts | 54 +- .../outbound/jose-sync-token-codec.ts | 1 + .../services/sync-token-service.ts | 6 +- .../verify-sync-token-service.test.ts | 48 + .../src/sync-access/domain/token-policy.ts | 3 + .../durable-object-rpc/sync-coordinator.ts | 62 +- .../adapters/inbound/http/routes.test.ts | 1 + .../adapters/inbound/http/routes.ts | 73 +- .../websocket/control-message-handler.ts | 36 +- .../coordinator-proxy-repository.ts | 86 +- .../scheduler/maintenance-scheduler.ts | 9 +- .../scheduler/node-maintenance-scheduler.ts | 4 +- .../socket/durable-object-service.test.ts | 26 + .../outbound/socket/durable-object-service.ts | 53 +- .../adapters/outbound/socket/node-service.ts | 9 +- .../outbound/sqlite/storage-lifecycle.ts | 1 + .../outbound/sqlite/sync-access-store.ts | 28 + .../sync-coordinator/application/dto/types.ts | 1 + .../ports/outbound/socket-gateway.ts | 1 + .../ports/outbound/sync-access-store.ts | 14 + .../services/bind-coordinator-api.ts | 2 + .../application/services/blob-gc-service.ts | 7 + .../services/socket-connection-service.ts | 18 + .../services/sync-access-service.test.ts | 184 ++ .../services/sync-access-service.ts | 142 ++ apps/api/src/sync-coordinator/test-helpers.ts | 1 + .../src/vault/adapters/inbound/http/routes.ts | 46 +- .../adapters/outbound/drizzle-vault-store.ts | 265 +-- .../application/dto/vault-key-envelope.ts | 7 +- .../ports/inbound/vault-service.ts | 10 +- .../ports/outbound/vault-key-store.ts | 7 +- .../services/vault-service.test.ts | 3 +- .../application/services/vault-service.ts | 48 +- apps/api/src/vault/domain/policy.test.ts | 11 +- apps/api/src/vault/domain/policy.ts | 14 +- apps/api/src/vault/domain/types.ts | 1 + .../test/integration/sharing-refresh.test.ts | 64 + apps/api/test/integration/sharing.test.ts | 493 +++++ .../subscription-policy-refresh.test.ts | 23 + apps/api/test/integration/vaults.test.ts | 56 +- apps/api/test/self-host/e2e.test.ts | 89 +- apps/api/vitest.config.mts | 1 + apps/api/wrangler.jsonc | 6 + apps/obsidian-plugin/release-notes/next.md | 4 + .../src/adapters/key-receiver-storage.ts | 44 + .../src/adapters/local-vault-content.test.ts | 42 + .../src/adapters/local-vault-content.ts | 15 + .../src/app/plugin-controller.ts | 31 + .../src/app/subscription-service.test.ts | 54 + .../src/app/subscription-service.ts | 33 +- apps/obsidian-plugin/src/i18n/locales/de.ts | 52 +- apps/obsidian-plugin/src/i18n/locales/en.ts | 48 + apps/obsidian-plugin/src/i18n/locales/ja.ts | 52 +- apps/obsidian-plugin/src/i18n/locales/ko.ts | 48 + .../obsidian-plugin/src/i18n/locales/zh-cn.ts | 52 +- .../obsidian-plugin/src/i18n/locales/zh-tw.ts | 52 +- .../src/test-stubs/obsidian.ts | 12 + apps/obsidian-plugin/src/ui/contracts.ts | 2 +- .../remote-vault/connect-vault-flow.test.ts | 195 ++ .../src/ui/remote-vault/connect-vault-flow.ts | 130 ++ .../remote-vault/connect-vault-modal.test.ts | 191 ++ .../ui/remote-vault/connect-vault-modal.ts | 258 +++ .../src/ui/remote-vault/ports.ts | 2 + .../remote-vault-controller.test.ts | 94 +- .../remote-vault/remote-vault-controller.ts | 52 +- .../remote-vault/remote-vault-modals.test.ts | 137 +- .../ui/remote-vault/remote-vault-modals.ts | 211 +- .../__tests__/settings-tab-helpers.ts | 1 + .../src/ui/settings/controller.ts | 1 + .../src/ui/settings/sections/remote-vault.ts | 1 + .../src/ui/settings/sections/subscription.ts | 2 + .../src/ui/settings/setting-definitions.ts | 3 + .../settings-tab-remote-vault.test.ts | 38 +- .../settings/settings-tab-sync-status.test.ts | 4 +- .../src/ui/settings/settings-tab.test.ts | 8 +- .../src/ui/sharing/sharing-modal.ts | 258 +++ apps/obsidian-plugin/styles.css | 206 ++ apps/www/package.json | 1 + apps/www/src/billing/pricing.ts | 5 + .../src/components/BillingSettingsPage.astro | 141 +- .../src/components/BillingSuccessPage.astro | 7 +- apps/www/src/components/PricingPage.astro | 66 +- apps/www/src/i18n.ts | 84 +- apps/www/test/billing-settings.test.mjs | 203 ++ apps/www/test/pricing-checkout.test.mjs | 84 + benchmarks/sync/src/compare.ts | 3 + packages/sync-client/src/billing/client.ts | 9 +- .../sync-client/src/remote-vault/client.ts | 7 +- .../remote-vault/manager.bootstrap.test.ts | 33 +- .../manager.organizations.test.ts | 39 + .../sync-client/src/remote-vault/manager.ts | 39 +- .../sync-client/src/remote-vault/types.ts | 1 + .../src/remote-vault/unavailable.ts | 2 +- packages/sync-client/src/remote.ts | 3 + .../sync-client/src/sharing/client.test.ts | 34 + packages/sync-client/src/sharing/client.ts | 161 ++ .../sync-client/src/sharing/manager.test.ts | 39 + packages/sync-client/src/sharing/manager.ts | 204 ++ .../sync/remote/realtime-socket-session.ts | 1 + packages/vault-crypto/src/crypto.ts | 50 +- packages/vault-crypto/src/index.ts | 1 + .../vault-crypto/src/key-transfer.test.ts | 117 ++ packages/vault-crypto/src/key-transfer.ts | 163 ++ packages/vault-crypto/src/types.ts | 6 + 167 files changed, 11103 insertions(+), 1028 deletions(-) create mode 100644 apps/api/drizzle-do/0008_sync_access_revocations.sql create mode 100644 apps/api/drizzle-do/meta/0008_snapshot.json create mode 100644 apps/api/drizzle/0007_plus_sharing.sql create mode 100644 apps/api/drizzle/meta/0007_snapshot.json create mode 100644 apps/api/public/invitations.html create mode 100644 apps/api/public/organization-ui.js create mode 100644 apps/api/public/organizations.html create mode 100644 apps/api/src/billing/adapters/outbound/drizzle-billing-store.test.ts create mode 100644 apps/api/src/db/d1/sharing-schema.ts create mode 100644 apps/api/src/sharing/adapters/drizzle-sharing-store.ts create mode 100644 apps/api/src/sharing/adapters/routes.ts create mode 100644 apps/api/src/sharing/application/access.ts create mode 100644 apps/api/src/sharing/application/refresh.ts create mode 100644 apps/api/src/sharing/application/service.ts create mode 100644 apps/api/src/sharing/application/store.ts create mode 100644 apps/api/src/sharing/application/types.ts create mode 100644 apps/api/src/sharing/migration.test.ts create mode 100644 apps/api/src/sharing/sharing.test.ts create mode 100644 apps/api/src/sync-access/application/services/verify-sync-token-service.test.ts create mode 100644 apps/api/src/sync-coordinator/adapters/outbound/sqlite/sync-access-store.ts create mode 100644 apps/api/src/sync-coordinator/application/ports/outbound/sync-access-store.ts create mode 100644 apps/api/src/sync-coordinator/application/services/sync-access-service.test.ts create mode 100644 apps/api/src/sync-coordinator/application/services/sync-access-service.ts create mode 100644 apps/api/test/integration/sharing-refresh.test.ts create mode 100644 apps/api/test/integration/sharing.test.ts create mode 100644 apps/obsidian-plugin/src/adapters/key-receiver-storage.ts create mode 100644 apps/obsidian-plugin/src/adapters/local-vault-content.test.ts create mode 100644 apps/obsidian-plugin/src/adapters/local-vault-content.ts create mode 100644 apps/obsidian-plugin/src/app/subscription-service.test.ts create mode 100644 apps/obsidian-plugin/src/ui/remote-vault/connect-vault-flow.test.ts create mode 100644 apps/obsidian-plugin/src/ui/remote-vault/connect-vault-flow.ts create mode 100644 apps/obsidian-plugin/src/ui/remote-vault/connect-vault-modal.test.ts create mode 100644 apps/obsidian-plugin/src/ui/remote-vault/connect-vault-modal.ts create mode 100644 apps/obsidian-plugin/src/ui/sharing/sharing-modal.ts create mode 100644 apps/www/src/billing/pricing.ts create mode 100644 apps/www/test/billing-settings.test.mjs create mode 100644 apps/www/test/pricing-checkout.test.mjs create mode 100644 packages/sync-client/src/remote-vault/manager.organizations.test.ts create mode 100644 packages/sync-client/src/sharing/client.test.ts create mode 100644 packages/sync-client/src/sharing/client.ts create mode 100644 packages/sync-client/src/sharing/manager.test.ts create mode 100644 packages/sync-client/src/sharing/manager.ts create mode 100644 packages/vault-crypto/src/key-transfer.test.ts create mode 100644 packages/vault-crypto/src/key-transfer.ts diff --git a/apps/api/drizzle-do/0008_sync_access_revocations.sql b/apps/api/drizzle-do/0008_sync_access_revocations.sql new file mode 100644 index 00000000..97ea53cb --- /dev/null +++ b/apps/api/drizzle-do/0008_sync_access_revocations.sql @@ -0,0 +1,7 @@ +CREATE TABLE `sync_access_revocations` ( + `key` text PRIMARY KEY NOT NULL, + `minimum_version` integer, + `expires_at` integer NOT NULL +); +--> statement-breakpoint +DELETE FROM `maintenance_jobs` WHERE `key` = 'sharing_access'; diff --git a/apps/api/drizzle-do/meta/0008_snapshot.json b/apps/api/drizzle-do/meta/0008_snapshot.json new file mode 100644 index 00000000..1cc698ba --- /dev/null +++ b/apps/api/drizzle-do/meta/0008_snapshot.json @@ -0,0 +1,526 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "8f3505f2-c1af-44b4-86b9-fd9f091b39f5", + "prevId": "64bf5baf-ff70-43eb-8310-fe4d564e865d", + "tables": { + "blobs": { + "name": "blobs", + "columns": { + "blob_id": { + "name": "blob_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "size_bytes": { + "name": "size_bytes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_uploaded_at": { + "name": "last_uploaded_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "delete_after": { + "name": "delete_after", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "idx_blobs_state_delete_after": { + "name": "idx_blobs_state_delete_after", + "columns": [ + "state", + "delete_after" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "coordinator_state": { + "name": "coordinator_state", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "vault_id": { + "name": "vault_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "current_cursor": { + "name": "current_cursor", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "storage_limit_bytes": { + "name": "storage_limit_bytes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "max_file_size_bytes": { + "name": "max_file_size_bytes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "version_history_retention_days": { + "name": "version_history_retention_days", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "last_commit_at": { + "name": "last_commit_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_gc_at": { + "name": "last_gc_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sync_paused_at": { + "name": "sync_paused_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sync_pause_reason": { + "name": "sync_pause_reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "entries": { + "name": "entries", + "columns": { + "entry_id": { + "name": "entry_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "blob_id": { + "name": "blob_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_metadata": { + "name": "encrypted_metadata", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "deleted": { + "name": "deleted", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "updated_seq": { + "name": "updated_seq", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_by_user_id": { + "name": "updated_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_by_local_vault_id": { + "name": "updated_by_local_vault_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_mutation_id": { + "name": "last_mutation_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "idx_entries_updated_seq_entry_id": { + "name": "idx_entries_updated_seq_entry_id", + "columns": [ + "updated_seq", + "entry_id" + ], + "isUnique": false + }, + "idx_entries_blob_id": { + "name": "idx_entries_blob_id", + "columns": [ + "blob_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "entry_versions": { + "name": "entry_versions", + "columns": { + "version_id": { + "name": "version_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "entry_id": { + "name": "entry_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_revision": { + "name": "source_revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "op_type": { + "name": "op_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "blob_id": { + "name": "blob_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_metadata": { + "name": "encrypted_metadata", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "bucket_start_ms": { + "name": "bucket_start_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "captured_at": { + "name": "captured_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_user_id": { + "name": "created_by_user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by_local_vault_id": { + "name": "created_by_local_vault_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_entry_versions_entry_captured_at": { + "name": "idx_entry_versions_entry_captured_at", + "columns": [ + "entry_id", + "captured_at", + "version_id" + ], + "isUnique": false + }, + "idx_entry_versions_auto_bucket": { + "name": "idx_entry_versions_auto_bucket", + "columns": [ + "entry_id", + "reason", + "bucket_start_ms" + ], + "isUnique": true + }, + "idx_entry_versions_expires_at": { + "name": "idx_entry_versions_expires_at", + "columns": [ + "expires_at" + ], + "isUnique": false + }, + "idx_entry_versions_blob_expires_at": { + "name": "idx_entry_versions_blob_expires_at", + "columns": [ + "blob_id", + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "local_vault_connections": { + "name": "local_vault_connections", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "local_vault_id": { + "name": "local_vault_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_connected_at": { + "name": "last_connected_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "local_vault_connections_user_id_local_vault_id_pk": { + "columns": [ + "user_id", + "local_vault_id" + ], + "name": "local_vault_connections_user_id_local_vault_id_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "maintenance_jobs": { + "name": "maintenance_jobs", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "due_at": { + "name": "due_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "retry_count": { + "name": "retry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_error_at": { + "name": "last_error_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_maintenance_jobs_due_at": { + "name": "idx_maintenance_jobs_due_at", + "columns": [ + "due_at" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sync_access_revocations": { + "name": "sync_access_revocations", + "columns": { + "minimum_version": { + "name": "minimum_version", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} diff --git a/apps/api/drizzle-do/meta/_journal.json b/apps/api/drizzle-do/meta/_journal.json index 3d6896c5..e766e6e8 100644 --- a/apps/api/drizzle-do/meta/_journal.json +++ b/apps/api/drizzle-do/meta/_journal.json @@ -57,6 +57,13 @@ "when": 1786857725150, "tag": "0007_aberrant_logan", "breakpoints": true + }, + { + "idx": 8, + "version": "6", + "when": 1790557279952, + "tag": "0008_sync_access_revocations", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/api/drizzle-do/migrations.js b/apps/api/drizzle-do/migrations.js index 3dc5bc02..8943d735 100644 --- a/apps/api/drizzle-do/migrations.js +++ b/apps/api/drizzle-do/migrations.js @@ -7,6 +7,7 @@ import m0004 from './0004_broad_jack_power.sql'; import m0005 from './0005_clever_killer_shrike.sql'; import m0006 from './0006_jazzy_rage.sql'; import m0007 from './0007_aberrant_logan.sql'; +import m0008 from './0008_sync_access_revocations.sql'; export default { journal, @@ -18,7 +19,8 @@ m0003, m0004, m0005, m0006, -m0007 +m0007, +m0008 } } \ No newline at end of file diff --git a/apps/api/drizzle/0007_plus_sharing.sql b/apps/api/drizzle/0007_plus_sharing.sql new file mode 100644 index 00000000..95c033d6 --- /dev/null +++ b/apps/api/drizzle/0007_plus_sharing.sql @@ -0,0 +1,73 @@ +CREATE TABLE `invitation_vault` ( + `invitation_id` text NOT NULL, + `vault_id` text NOT NULL, + PRIMARY KEY(`invitation_id`, `vault_id`), + FOREIGN KEY (`invitation_id`) REFERENCES `invitation`(`id`) ON UPDATE no action ON DELETE cascade, + FOREIGN KEY (`vault_id`) REFERENCES `vault`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE TABLE `sharing_audit` ( + `id` text PRIMARY KEY NOT NULL, + `organization_id` text NOT NULL, + `actor_id` text NOT NULL, + `action` text NOT NULL, + `target_id` text NOT NULL, + `created_at` integer NOT NULL, + FOREIGN KEY (`organization_id`) REFERENCES `organization`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE INDEX `sharing_audit_org_idx` ON `sharing_audit` (`organization_id`,`created_at`);--> statement-breakpoint +CREATE TABLE `sharing_refresh` ( + `vault_id` text PRIMARY KEY NOT NULL, + `revision` text NOT NULL, + `created_at` integer NOT NULL, + FOREIGN KEY (`vault_id`) REFERENCES `vault`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE TABLE `vault_key_request` ( + `id` text PRIMARY KEY NOT NULL, + `vault_id` text NOT NULL, + `user_id` text NOT NULL, + `purpose` text NOT NULL, + `access_version` integer NOT NULL, + `public_key` text NOT NULL, + `status` text NOT NULL, + `envelope_json` text, + `approved_by` text, + `created_at` integer NOT NULL, + `expires_at` integer NOT NULL, + FOREIGN KEY (`vault_id`) REFERENCES `vault`(`id`) ON UPDATE no action ON DELETE cascade, + FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade, + FOREIGN KEY (`approved_by`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action +); +--> statement-breakpoint +CREATE INDEX `vault_key_request_vault_status_idx` ON `vault_key_request` (`vault_id`,`status`);--> statement-breakpoint +CREATE INDEX `vault_key_request_user_idx` ON `vault_key_request` (`user_id`);--> statement-breakpoint +ALTER TABLE `vault` ADD `shared_at` integer;--> statement-breakpoint +ALTER TABLE `vault_membership` ADD `access_version` integer DEFAULT 1 NOT NULL; +--> statement-breakpoint +ALTER TABLE `vault_membership` ADD `explicit_access` integer DEFAULT true NOT NULL; +--> statement-breakpoint +ALTER TABLE `vault_membership` ADD `is_creator` integer DEFAULT false NOT NULL; +--> statement-breakpoint +UPDATE vault_membership SET is_creator = (role = 'owner'); +--> statement-breakpoint +ALTER TABLE `vault_membership` DROP COLUMN `role`; +--> statement-breakpoint +-- Preserve legacy shared-password access for existing active users before disabling +-- the unscoped wrapper fallback on shared vaults. No key is decrypted or rotated. +INSERT INTO vault_key_wrapper (id, vault_id, key_version, kind, user_id, envelope_json, created_at, revoked_at) +SELECT lower(hex(randomblob(16))), w.vault_id, w.key_version, 'password', m.user_id, w.envelope_json, w.created_at, NULL +FROM vault_key_wrapper w +JOIN vault v ON v.id = w.vault_id AND v.active_key_version = w.key_version +JOIN vault_membership m ON m.vault_id = w.vault_id AND m.status = 'active' +JOIN member om ON om.organization_id = v.organization_id AND om.user_id = m.user_id +WHERE w.kind = 'password' AND w.user_id IS NULL AND w.revoked_at IS NULL +AND w.id = (SELECT old.id FROM vault_key_wrapper old + WHERE old.vault_id = w.vault_id AND old.kind = 'password' AND old.user_id IS NULL + AND old.revoked_at IS NULL AND old.key_version = v.active_key_version + ORDER BY old.created_at DESC, old.id DESC LIMIT 1) +ON CONFLICT (vault_id, kind, user_id) DO NOTHING; +--> statement-breakpoint +UPDATE vault SET shared_at = created_at +WHERE (SELECT count(*) FROM vault_membership m WHERE m.vault_id = vault.id AND m.status != 'revoked') > 1; diff --git a/apps/api/drizzle/meta/0007_snapshot.json b/apps/api/drizzle/meta/0007_snapshot.json new file mode 100644 index 00000000..7e0ce889 --- /dev/null +++ b/apps/api/drizzle/meta/0007_snapshot.json @@ -0,0 +1,1774 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "3c5e57c5-f6bc-4863-a824-417df9e6e7f8", + "prevId": "91325ebc-6c89-495d-b45a-f2510b635d5f", + "tables": { + "account": { + "name": "account", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "issuer": { + "name": "issuer", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'local:credential'" + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "account_issuer_accountId_uidx": { + "name": "account_issuer_accountId_uidx", + "columns": [ + "issuer", + "account_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "device_code": { + "name": "device_code", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "device_code": { + "name": "device_code", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_code": { + "name": "user_code", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_polled_at": { + "name": "last_polled_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "polling_interval": { + "name": "polling_interval", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "device_code_deviceCode_uidx": { + "name": "device_code_deviceCode_uidx", + "columns": [ + "device_code" + ], + "isUnique": true + }, + "device_code_userCode_uidx": { + "name": "device_code_userCode_uidx", + "columns": [ + "user_code" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "invitation": { + "name": "invitation", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'pending'" + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))" + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "invitation_organizationId_idx": { + "name": "invitation_organizationId_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "invitation_email_idx": { + "name": "invitation_email_idx", + "columns": [ + "email" + ], + "isUnique": false + } + }, + "foreignKeys": { + "invitation_organization_id_organization_id_fk": { + "name": "invitation_organization_id_organization_id_fk", + "tableFrom": "invitation", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitation_inviter_id_user_id_fk": { + "name": "invitation_inviter_id_user_id_fk", + "tableFrom": "invitation", + "tableTo": "user", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "member": { + "name": "member", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'member'" + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "member_organizationId_idx": { + "name": "member_organizationId_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "member_userId_idx": { + "name": "member_userId_idx", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "member_organization_id_organization_id_fk": { + "name": "member_organization_id_organization_id_fk", + "tableFrom": "member", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_user_id_user_id_fk": { + "name": "member_user_id_user_id_fk", + "tableFrom": "member", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "organization": { + "name": "organization", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slug": { + "name": "slug", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "polar_customer_id": { + "name": "polar_customer_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "synced_vaults_override": { + "name": "synced_vaults_override", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "organization_slug_unique": { + "name": "organization_slug_unique", + "columns": [ + "slug" + ], + "isUnique": true + }, + "organization_polar_customer_id_unique": { + "name": "organization_polar_customer_id_unique", + "columns": [ + "polar_customer_id" + ], + "isUnique": true + }, + "organization_slug_uidx": { + "name": "organization_slug_uidx", + "columns": [ + "slug" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "session": { + "name": "session", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "active_organization_id": { + "name": "active_organization_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "session_token_unique": { + "name": "session_token_unique", + "columns": [ + "token" + ], + "isUnique": true + }, + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "user": { + "name": "user", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email_verified": { + "name": "email_verified", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))" + } + }, + "indexes": { + "user_email_unique": { + "name": "user_email_unique", + "columns": [ + "email" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "verification": { + "name": "verification", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))" + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + "identifier" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "polar_subscription": { + "name": "polar_subscription", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "product_id": { + "name": "product_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "polar_customer_id": { + "name": "polar_customer_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "polar_subscription_id": { + "name": "polar_subscription_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "polar_checkout_id": { + "name": "polar_checkout_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "period_start": { + "name": "period_start", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "period_end": { + "name": "period_end", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cancel_at_period_end": { + "name": "cancel_at_period_end", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))" + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast(unixepoch('subsecond') * 1000 as integer))" + } + }, + "indexes": { + "polar_subscription_organizationId_idx": { + "name": "polar_subscription_organizationId_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "polar_subscription_customerId_idx": { + "name": "polar_subscription_customerId_idx", + "columns": [ + "polar_customer_id" + ], + "isUnique": false + }, + "polar_subscription_status_idx": { + "name": "polar_subscription_status_idx", + "columns": [ + "status", + "period_end" + ], + "isUnique": false + }, + "polar_subscription_polarSubscriptionId_uidx": { + "name": "polar_subscription_polarSubscriptionId_uidx", + "columns": [ + "polar_subscription_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "polar_subscription_organization_id_organization_id_fk": { + "name": "polar_subscription_organization_id_organization_id_fk", + "tableFrom": "polar_subscription", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "vault": { + "name": "vault", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "shared_at": { + "name": "shared_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "active_key_version": { + "name": "active_key_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + }, + "deleted_at": { + "name": "deleted_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "purge_status": { + "name": "purge_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "purge_error": { + "name": "purge_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "vault_organizationId_idx": { + "name": "vault_organizationId_idx", + "columns": [ + "organization_id" + ], + "isUnique": false + }, + "vault_deletedAt_idx": { + "name": "vault_deletedAt_idx", + "columns": [ + "deleted_at" + ], + "isUnique": false + }, + "vault_organization_name_active_uidx": { + "name": "vault_organization_name_active_uidx", + "columns": [ + "organization_id", + "name" + ], + "isUnique": true, + "where": "\"vault\".\"deleted_at\" is null" + } + }, + "foreignKeys": { + "vault_organization_id_organization_id_fk": { + "name": "vault_organization_id_organization_id_fk", + "tableFrom": "vault", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "vault_key_wrapper": { + "name": "vault_key_wrapper", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "vault_id": { + "name": "vault_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key_version": { + "name": "key_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "envelope_json": { + "name": "envelope_json", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + }, + "revoked_at": { + "name": "revoked_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "vault_key_wrapper_vaultId_idx": { + "name": "vault_key_wrapper_vaultId_idx", + "columns": [ + "vault_id" + ], + "isUnique": false + }, + "vault_key_wrapper_userId_idx": { + "name": "vault_key_wrapper_userId_idx", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "vault_key_wrapper_vault_kind_user_unique": { + "name": "vault_key_wrapper_vault_kind_user_unique", + "columns": [ + "vault_id", + "kind", + "user_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "vault_key_wrapper_vault_id_vault_id_fk": { + "name": "vault_key_wrapper_vault_id_vault_id_fk", + "tableFrom": "vault_key_wrapper", + "tableTo": "vault", + "columnsFrom": [ + "vault_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "vault_key_wrapper_user_id_user_id_fk": { + "name": "vault_key_wrapper_user_id_user_id_fk", + "tableFrom": "vault_key_wrapper", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "vault_membership": { + "name": "vault_membership", + "columns": { + "vault_id": { + "name": "vault_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "access_version": { + "name": "access_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "joined_at": { + "name": "joined_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(cast((julianday('now') - 2440587.5)*86400000 as integer))" + }, + "revoked_at": { + "name": "revoked_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "explicit_access": { + "name": "explicit_access", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "is_creator": { + "name": "is_creator", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + } + }, + "indexes": { + "vault_membership_userId_status_idx": { + "name": "vault_membership_userId_status_idx", + "columns": [ + "user_id", + "status" + ], + "isUnique": false + }, + "vault_membership_vaultId_status_idx": { + "name": "vault_membership_vaultId_status_idx", + "columns": [ + "vault_id", + "status" + ], + "isUnique": false + } + }, + "foreignKeys": { + "vault_membership_vault_id_vault_id_fk": { + "name": "vault_membership_vault_id_vault_id_fk", + "tableFrom": "vault_membership", + "tableTo": "vault", + "columnsFrom": [ + "vault_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "vault_membership_user_id_user_id_fk": { + "name": "vault_membership_user_id_user_id_fk", + "tableFrom": "vault_membership", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "vault_membership_vault_id_user_id_pk": { + "columns": [ + "vault_id", + "user_id" + ], + "name": "vault_membership_vault_id_user_id_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "vault_sync_status": { + "name": "vault_sync_status", + "columns": { + "vault_id": { + "name": "vault_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "health_status": { + "name": "health_status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'unknown'" + }, + "health_reasons_json": { + "name": "health_reasons_json", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'[]'" + }, + "current_cursor": { + "name": "current_cursor", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "entry_count": { + "name": "entry_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "live_blob_count": { + "name": "live_blob_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "staged_blob_count": { + "name": "staged_blob_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "pending_delete_blob_count": { + "name": "pending_delete_blob_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "storage_used_bytes": { + "name": "storage_used_bytes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "storage_limit_bytes": { + "name": "storage_limit_bytes", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "active_local_vault_count": { + "name": "active_local_vault_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "websocket_count": { + "name": "websocket_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "oldest_staged_blob_age_ms": { + "name": "oldest_staged_blob_age_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "oldest_pending_delete_age_ms": { + "name": "oldest_pending_delete_age_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_commit_at": { + "name": "last_commit_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_gc_at": { + "name": "last_gc_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_flushed_at": { + "name": "last_flushed_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "vault_sync_status_health_idx": { + "name": "vault_sync_status_health_idx", + "columns": [ + "health_status", + "updated_at" + ], + "isUnique": false + }, + "vault_sync_status_storage_idx": { + "name": "vault_sync_status_storage_idx", + "columns": [ + "storage_used_bytes", + "storage_limit_bytes" + ], + "isUnique": false + } + }, + "foreignKeys": { + "vault_sync_status_vault_id_vault_id_fk": { + "name": "vault_sync_status_vault_id_vault_id_fk", + "tableFrom": "vault_sync_status", + "tableTo": "vault", + "columnsFrom": [ + "vault_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "invitation_vault": { + "name": "invitation_vault", + "columns": { + "invitation_id": { + "name": "invitation_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "vault_id": { + "name": "vault_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "invitation_vault_invitation_id_invitation_id_fk": { + "name": "invitation_vault_invitation_id_invitation_id_fk", + "tableFrom": "invitation_vault", + "tableTo": "invitation", + "columnsFrom": [ + "invitation_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "invitation_vault_vault_id_vault_id_fk": { + "name": "invitation_vault_vault_id_vault_id_fk", + "tableFrom": "invitation_vault", + "tableTo": "vault", + "columnsFrom": [ + "vault_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "invitation_vault_invitation_id_vault_id_pk": { + "columns": [ + "invitation_id", + "vault_id" + ], + "name": "invitation_vault_invitation_id_vault_id_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sharing_audit": { + "name": "sharing_audit", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "organization_id": { + "name": "organization_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "actor_id": { + "name": "actor_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_id": { + "name": "target_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "sharing_audit_org_idx": { + "name": "sharing_audit_org_idx", + "columns": [ + "organization_id", + "created_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sharing_audit_organization_id_organization_id_fk": { + "name": "sharing_audit_organization_id_organization_id_fk", + "tableFrom": "sharing_audit", + "tableTo": "organization", + "columnsFrom": [ + "organization_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sharing_refresh": { + "name": "sharing_refresh", + "columns": { + "vault_id": { + "name": "vault_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "revision": { + "name": "revision", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "sharing_refresh_vault_id_vault_id_fk": { + "name": "sharing_refresh_vault_id_vault_id_fk", + "tableFrom": "sharing_refresh", + "tableTo": "vault", + "columnsFrom": [ + "vault_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "vault_key_request": { + "name": "vault_key_request", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "vault_id": { + "name": "vault_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "purpose": { + "name": "purpose", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "access_version": { + "name": "access_version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "envelope_json": { + "name": "envelope_json", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "approved_by": { + "name": "approved_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "vault_key_request_vault_status_idx": { + "name": "vault_key_request_vault_status_idx", + "columns": [ + "vault_id", + "status" + ], + "isUnique": false + }, + "vault_key_request_user_idx": { + "name": "vault_key_request_user_idx", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "vault_key_request_vault_id_vault_id_fk": { + "name": "vault_key_request_vault_id_vault_id_fk", + "tableFrom": "vault_key_request", + "tableTo": "vault", + "columnsFrom": [ + "vault_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "vault_key_request_user_id_user_id_fk": { + "name": "vault_key_request_user_id_user_id_fk", + "tableFrom": "vault_key_request", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "vault_key_request_approved_by_user_id_fk": { + "name": "vault_key_request_approved_by_user_id_fk", + "tableFrom": "vault_key_request", + "tableTo": "user", + "columnsFrom": [ + "approved_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} diff --git a/apps/api/drizzle/meta/_journal.json b/apps/api/drizzle/meta/_journal.json index 9e91c535..1542a486 100644 --- a/apps/api/drizzle/meta/_journal.json +++ b/apps/api/drizzle/meta/_journal.json @@ -50,6 +50,13 @@ "when": 1787664774337, "tag": "0006_mute_bloodstrike", "breakpoints": true + }, + { + "idx": 7, + "version": "6", + "when": 1790485061751, + "tag": "0007_plus_sharing", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/api/public/i18n/de.json b/apps/api/public/i18n/de.json index 8a068e77..aff04571 100644 --- a/apps/api/public/i18n/de.json +++ b/apps/api/public/i18n/de.json @@ -87,7 +87,7 @@ "createNameLabel": "Vault-Name", "createPasswordLabel": "Vault-Passwort", "createConfirmPasswordLabel": "Vault-Passwort (Bestätigung)", - "createPasswordHint": "Das Passwort kann nicht wiederhergestellt werden. Bewahren Sie es sicher auf. Geben Sie dasselbe Passwort ein, wenn Sie dieses Vault in Obsidian verbinden.", + "createPasswordHint": "Bewahre dieses Passwort sicher auf. Bei Verlust muss ein anderer Vault-Administrator, der den Vault-Schlüssel noch besitzt, die Wiederherstellung genehmigen.", "createConfirm": "Vault erstellen", "creating": "Wird erstellt...", "createdVault": "{name} wurde erstellt. Verbinden Sie es in Obsidian mit demselben Vault-Passwort.", @@ -132,6 +132,85 @@ "queuedForDeletion": "{name} wurde in die Löschwarteschlange gestellt.", "unknown": "Unbekannt", "created": "Erstellt am {date}", - "deletionStatus": "Löschen {status}" + "deletionStatus": "Löschen {status}", + "organization": "Organisation", + "organizations": "Organisationen verwalten" + }, + "organizations": { + "title": "Organisationen", + "subtitle": "Verwalte Mitglieder, Einladungen und den Zugriff auf verschlüsselte Vaults.", + "name": "Organisationsname", + "rename": "Umbenennen", + "organizationRole": "Organisationsrolle", + "role": "Rolle", + "email": "E-Mail-Adresse", + "invite": "Mitglied einladen", + "inviteHelp": "Wähle die Vaults, auf die dieses Mitglied zugreifen und die es bearbeiten kann. Eigentümer und Administratoren können auf alle Vaults zugreifen und sie verwalten. Ausstehende Einladungen reservieren Mitgliedsplätze.", + "selectVault": "Wähle mindestens einen Vault.", + "sent": "Einladungs-E-Mail gesendet.", + "copyLink": "Kopiere diesen Link und teile ihn mit der eingeladenen Person. Sie muss sich mit der eingeladenen E-Mail-Adresse anmelden.", + "inviteLink": "Einladungslink", + "invitations": "Einladungen", + "members": "Mitglieder", + "remove": "Mitglied entfernen", + "revoke": "Zugriff entziehen", + "grant": "Zugriff gewähren", + "leave": "Organisation verlassen", + "removeConfirm": "Synchronisierung für diese Person beenden? Bereits heruntergeladene Dateien bleiben auf ihren Geräten.", + "pendingRefresh": "Zugriff entzogen. Bestehende Verbindungen werden geschlossen. Aktualisiere die Seite zur Kontrolle.", + "noAccess": "Kein Zugriff", + "yourAccess": "Dein Zugriff", + "owner": "Eigentümer", + "admin": "Administrator", + "member": "Mitglied", + "active": "Aktiv", + "pending_key": "Wartet auf Schlüsseleinrichtung", + "revoked": "Entzogen", + "pending": "Ausstehend", + "expired": "Abgelaufen", + "canceled": "Abgebrochen", + "rejected": "Abgelehnt", + "accepted": "Angenommen", + "refresh": "Aktualisieren", + "working": "Speichern…", + "saved": "Gespeichert.", + "failed": "Anfrage konnte nicht abgeschlossen werden.", + "signIn": "Bitte melde dich an.", + "loaded": "Organisation geladen.", + "noOrganizations": "Keine Organisationen gefunden.", + "noVaults": "Keine Vaults verfügbar. Erstelle einen unter Remote-Vaults oder bitte einen Administrator um Zugriff.", + "suspended": "Gemeinsame Synchronisierung pausiert. Die Daten bleiben erhalten. Nach Erneuerung von Plus wird der Zugriff fortgesetzt.", + "keyHelp": "Öffne in Obsidian Synch → Vault-Freigabe und Passwörter, um Zugriff anzufordern oder zu genehmigen und dein eigenes Passwort festzulegen. Gespeicherte Versionen werden ebenfalls geteilt.", + "plusLimits": "Plus: 3 Mitglieder einschließlich Eigentümer · 3 Vaults · 2 GB pro Vault · 100 MB pro Datei · 1 Jahr Versionsverlauf", + "cancel": "Einladung abbrechen", + "resend": "Erneut senden", + "vaults": "Remote-Vaults", + "organization": "Organisation", + "billing": "Abrechnung verwalten", + "sharingRequired": "Organisationsfreigaben sind mit Plus oder auf selbst gehosteten Servern verfügbar." + }, + "invitations": { + "organizationRole": "Organisationsrolle", + "owner": "Eigentümer", + "admin": "Administrator", + "member": "Mitglied", + "pending": "Ausstehend", + "expired": "Abgelaufen", + "canceled": "Abgebrochen", + "rejected": "Abgelehnt", + "accepted": "Angenommen", + "failed": "Anfrage konnte nicht abgeschlossen werden.", + "signIn": "Bitte melde dich an.", + "title": "Organisationseinladung", + "subtitle": "Prüfe die Vault-Berechtigungen dieser Einladung.", + "missing": "Öffne den Einladungslink deines Administrators.", + "history": "Nach Annahme und Schlüsselfreigabe erhältst du auch Zugriff auf gespeicherte Versionen.", + "keyHelp": "Öffne nach der Annahme im Synch-Obsidian-Plugin auf deinem Gerät die Vault-Freigabe und Passwörter. Fordere eine Administratorfreigabe an und lege dein eigenes Passwort fest.", + "accept": "Einladung annehmen", + "reject": "Einladung ablehnen", + "next": "Einladung angenommen. Setze die Schlüsseleinrichtung in Obsidian fort.", + "organizations": "Organisation verwalten", + "switchAccount": "Konto wechseln", + "wrongAccount": "Diese Einladung ist für dieses Konto nicht verfügbar. Melde dich mit der eingeladenen E-Mail-Adresse an." } } diff --git a/apps/api/public/i18n/ja.json b/apps/api/public/i18n/ja.json index 024da174..63509c86 100644 --- a/apps/api/public/i18n/ja.json +++ b/apps/api/public/i18n/ja.json @@ -87,7 +87,7 @@ "createNameLabel": "Vault 名", "createPasswordLabel": "Vault パスワード", "createConfirmPasswordLabel": "Vault パスワード(確認)", - "createPasswordHint": "パスワードは復元できないため、安全な場所に保管してください。Obsidian からこの vault に接続する際に同じパスワードを入力します。", + "createPasswordHint": "パスワードを安全に保管してください。紛失時の復旧にはvaultキーを持つ別のvault管理者の承認が必要です。", "createConfirm": "Vault を作成", "creating": "作成中...", "createdVault": "{name} を作成しました。Obsidian から同じ vault パスワードで接続してください。", @@ -132,6 +132,85 @@ "queuedForDeletion": "{name}を削除キューに追加しました。", "unknown": "不明", "created": "作成日 {date}", - "deletionStatus": "削除 {status}" + "deletionStatus": "削除 {status}", + "organization": "組織", + "organizations": "組織を管理" + }, + "organizations": { + "title": "組織の管理", + "subtitle": "メンバー、招待、暗号化された Vault へのアクセスを管理します。", + "name": "組織名", + "rename": "名前を変更", + "organizationRole": "組織の役割", + "role": "役割", + "email": "メールアドレス", + "invite": "メンバーを招待", + "inviteHelp": "メンバーがアクセス・編集できる保管庫を選択してください。所有者と管理者はすべての保管庫にアクセスして管理できます。保留中の招待もメンバー数に含まれます。", + "selectVault": "Vault を1つ以上選択してください。", + "sent": "招待メールを送信しました。", + "copyLink": "この招待リンクをコピーして相手に伝えてください。招待されたメールアドレスでログインする必要があります。", + "inviteLink": "招待リンク", + "invitations": "招待", + "members": "メンバー", + "remove": "メンバーを削除", + "revoke": "アクセスを取り消す", + "grant": "アクセスを許可", + "leave": "組織から退出", + "removeConfirm": "この人の同期アクセスを停止しますか?端末にダウンロード済みのファイルは残ります。", + "pendingRefresh": "アクセスを取り消しました。既存の接続を終了中です。更新して確認してください。", + "noAccess": "アクセスなし", + "yourAccess": "自分の権限", + "owner": "所有者", + "admin": "管理者", + "member": "メンバー", + "active": "有効", + "pending_key": "キー設定待ち", + "revoked": "取り消し済み", + "pending": "承諾待ち", + "expired": "期限切れ", + "canceled": "キャンセル済み", + "rejected": "拒否済み", + "accepted": "承諾済み", + "refresh": "更新", + "working": "保存中…", + "saved": "保存しました。", + "failed": "リクエストを完了できません。", + "signIn": "ログインしてください。", + "loaded": "組織を読み込みました。", + "noOrganizations": "組織がありません。", + "noVaults": "利用可能な Vault がありません。リモート Vault で作成するか、管理者にアクセスを申請してください。", + "suspended": "共有同期は停止中です。データは保持され、Plus を再契約するとアクセスが再開します。", + "keyHelp": "Obsidian の Synch → Vault の共有とパスワードでアクセスを申請・承認し、自分の Vault パスワードを設定してください。保存済みの履歴も共有されます。", + "plusLimits": "Plus:所有者を含む3名 · Vault 3個 · 各 Vault 2 GB · ファイルあたり100 MB · 履歴1年", + "cancel": "招待をキャンセル", + "resend": "再送信", + "vaults": "リモート Vault", + "organization": "組織", + "billing": "請求を管理", + "sharingRequired": "Plusまたはセルフホスト環境で組織のvaultを共有できます。" + }, + "invitations": { + "organizationRole": "組織の役割", + "owner": "所有者", + "admin": "管理者", + "member": "メンバー", + "pending": "承諾待ち", + "expired": "期限切れ", + "canceled": "キャンセル済み", + "rejected": "拒否済み", + "accepted": "承諾済み", + "failed": "リクエストを完了できません。", + "signIn": "ログインしてください。", + "title": "組織への招待", + "subtitle": "招待に含まれる Vault のアクセス権を確認してください。", + "missing": "管理者から受け取った招待リンクを開いてください。", + "history": "承諾してキーの承認を受けると、保存済みの履歴にもアクセスできます。", + "keyHelp": "承諾後、使用する端末の Synch Obsidian プラグインで Vault の共有とパスワードを開き、管理者に承認を申請して自分のパスワードを設定してください。", + "accept": "招待を承諾", + "reject": "招待を拒否", + "next": "招待を承諾しました。Obsidian でキー設定を続けてください。", + "organizations": "組織を管理", + "switchAccount": "アカウントを切り替え", + "wrongAccount": "このアカウントでは招待を開けません。招待を受け取ったメールアドレスでログインしてください。" } } diff --git a/apps/api/public/i18n/ko.json b/apps/api/public/i18n/ko.json index 7e034508..f484a58c 100644 --- a/apps/api/public/i18n/ko.json +++ b/apps/api/public/i18n/ko.json @@ -87,7 +87,7 @@ "createNameLabel": "Vault 이름", "createPasswordLabel": "Vault 비밀번호", "createConfirmPasswordLabel": "Vault 비밀번호 확인", - "createPasswordHint": "비밀번호는 복구할 수 없으니 안전한 곳에 보관하세요. Obsidian에서 이 vault를 연결할 때 같은 비밀번호를 입력합니다.", + "createPasswordHint": "비밀번호를 안전하게 보관하세요. 분실 시 vault 키를 가진 다른 vault 관리자의 승인이 있어야 복구할 수 있습니다.", "createConfirm": "Vault 생성", "creating": "생성 중...", "createdVault": "{name}이(가) 생성되었습니다. Obsidian에서 같은 vault 비밀번호로 연결하세요.", @@ -132,6 +132,85 @@ "queuedForDeletion": "{name} 삭제가 대기열에 추가되었습니다.", "unknown": "알 수 없음", "created": "생성일 {date}", - "deletionStatus": "삭제 {status}" + "deletionStatus": "삭제 {status}", + "organization": "조직", + "organizations": "조직 관리" + }, + "organizations": { + "title": "조직 관리", + "subtitle": "멤버, 초대, 암호화된 vault의 접근 권한을 관리합니다.", + "name": "조직 이름", + "rename": "이름 변경", + "organizationRole": "조직 역할", + "role": "역할", + "email": "이메일 주소", + "invite": "멤버 초대", + "inviteHelp": "멤버가 접근하고 편집할 vault를 선택하세요. 소유자와 관리자는 모든 vault에 접근하고 관리할 수 있습니다. 대기 중인 초대도 멤버 수에 포함됩니다.", + "selectVault": "Vault를 하나 이상 선택하세요.", + "sent": "초대 이메일을 보냈습니다.", + "copyLink": "초대 링크를 복사해 초대한 사람에게 전달하세요. 초대받은 이메일 주소로 로그인해야 합니다.", + "inviteLink": "초대 링크", + "invitations": "초대", + "members": "멤버", + "remove": "멤버 제거", + "revoke": "접근 회수", + "grant": "접근 허용", + "leave": "조직 탈퇴", + "removeConfirm": "이 사람의 동기화 접근을 중지할까요? 이미 기기에 내려받은 파일은 유지됩니다.", + "pendingRefresh": "접근 권한을 회수했습니다. 기존 연결을 종료 중이니 새로고침해 확인하세요.", + "noAccess": "접근 없음", + "yourAccess": "내 권한", + "owner": "소유자", + "admin": "관리자", + "member": "멤버", + "active": "활성", + "pending_key": "키 설정 대기", + "revoked": "회수됨", + "pending": "수락 대기", + "expired": "만료됨", + "canceled": "취소됨", + "rejected": "거절됨", + "accepted": "수락됨", + "refresh": "새로고침", + "working": "저장 중…", + "saved": "저장했습니다.", + "failed": "요청을 완료할 수 없습니다.", + "signIn": "로그인해 주세요.", + "loaded": "조직을 불러왔습니다.", + "noOrganizations": "조직이 없습니다.", + "noVaults": "사용 가능한 vault가 없습니다. 원격 vault에서 생성하거나 관리자에게 접근을 요청하세요.", + "suspended": "공유 동기화가 중지되었습니다. 데이터는 보존되며 Plus를 재구독하면 접근이 재개됩니다.", + "keyHelp": "Obsidian의 Synch → Vault 공유 및 비밀번호에서 접근을 요청·승인하고 개인 vault 비밀번호를 설정하세요. 보관된 과거 이력도 공유됩니다.", + "plusLimits": "Plus: 소유자 포함 3명 · Vault 3개 · Vault별 2 GB · 파일당 100 MB · 이력 1년", + "cancel": "초대 취소", + "resend": "재전송", + "vaults": "원격 vault", + "organization": "조직", + "billing": "구독 관리", + "sharingRequired": "Plus 또는 self-hosted에서 조직의 vault를 공유할 수 있습니다." + }, + "invitations": { + "organizationRole": "조직 역할", + "owner": "소유자", + "admin": "관리자", + "member": "멤버", + "pending": "수락 대기", + "expired": "만료됨", + "canceled": "취소됨", + "rejected": "거절됨", + "accepted": "수락됨", + "failed": "요청을 완료할 수 없습니다.", + "signIn": "로그인해 주세요.", + "title": "조직 초대", + "subtitle": "초대에 포함된 vault 접근 권한을 확인하세요.", + "missing": "관리자가 제공한 초대 링크를 열어주세요.", + "history": "초대를 수락하고 키 승인을 받으면 보관된 과거 이력에도 접근할 수 있습니다.", + "keyHelp": "수락 후 사용할 기기의 Synch Obsidian 플러그인에서 Vault 공유 및 비밀번호를 열어 관리자 승인을 요청하고 자신의 vault 비밀번호를 설정하세요.", + "accept": "초대 수락", + "reject": "초대 거절", + "next": "초대를 수락했습니다. Obsidian에서 키 설정을 계속하세요.", + "organizations": "조직 관리", + "switchAccount": "계정 전환", + "wrongAccount": "이 계정에서는 초대를 열 수 없습니다. 초대를 받은 이메일 주소로 로그인하세요." } } diff --git a/apps/api/public/i18n/zh-cn.json b/apps/api/public/i18n/zh-cn.json index 69e3b0aa..0121a064 100644 --- a/apps/api/public/i18n/zh-cn.json +++ b/apps/api/public/i18n/zh-cn.json @@ -87,7 +87,7 @@ "createNameLabel": "Vault 名称", "createPasswordLabel": "Vault 密码", "createConfirmPasswordLabel": "确认 vault 密码", - "createPasswordHint": "密码无法找回,请妥善保管。在 Obsidian 中连接此 vault 时需要输入相同的密码。", + "createPasswordHint": "请妥善保管密码。丢失后,需要仍持有 vault 密钥的其他 vault 管理员批准才能恢复。", "createConfirm": "创建 vault", "creating": "创建中...", "createdVault": "{name} 已创建。请在 Obsidian 中使用相同的 vault 密码连接。", @@ -132,6 +132,85 @@ "queuedForDeletion": "{name} 已加入删除队列。", "unknown": "未知", "created": "创建于 {date}", - "deletionStatus": "删除 {status}" + "deletionStatus": "删除 {status}", + "organization": "组织", + "organizations": "管理组织" + }, + "organizations": { + "title": "组织管理", + "subtitle": "管理成员、邀请以及加密 Vault 的访问权限。", + "name": "组织名称", + "rename": "重命名", + "organizationRole": "组织角色", + "role": "角色", + "email": "电子邮件地址", + "invite": "邀请成员", + "inviteHelp": "选择此成员可以访问和编辑的保险库。所有者和管理员可以访问和管理所有保险库。待处理的邀请也会占用成员名额。", + "selectVault": "请至少选择一个 Vault。", + "sent": "邀请邮件已发送。", + "copyLink": "复制此邀请链接并发送给受邀人。对方必须使用受邀的电子邮件地址登录。", + "inviteLink": "邀请链接", + "invitations": "邀请", + "members": "成员", + "remove": "移除成员", + "revoke": "撤销访问", + "grant": "授予访问", + "leave": "退出组织", + "removeConfirm": "停止此人的同步访问?已下载到设备上的文件仍会保留。", + "pendingRefresh": "访问权限已撤销,正在关闭现有连接。请刷新以确认。", + "noAccess": "无访问权限", + "yourAccess": "我的权限", + "owner": "所有者", + "admin": "管理员", + "member": "成员", + "active": "已启用", + "pending_key": "等待密钥设置", + "revoked": "已撤销", + "pending": "待接受", + "expired": "已过期", + "canceled": "已取消", + "rejected": "已拒绝", + "accepted": "已接受", + "refresh": "刷新", + "working": "保存中…", + "saved": "已保存。", + "failed": "无法完成请求。", + "signIn": "请登录。", + "loaded": "组织已加载。", + "noOrganizations": "没有组织。", + "noVaults": "没有可用的 Vault。请在远程 Vault 中创建,或向管理员申请访问。", + "suspended": "共享同步已暂停。数据会保留,续订 Plus 后将恢复访问。", + "keyHelp": "在 Obsidian 的 Synch → Vault 共享与密码中申请或批准访问,并设置个人 Vault 密码。保留的历史记录也会共享。", + "plusLimits": "Plus:含所有者共 3 人 · 3 个 Vault · 每个 Vault 2 GB · 每个文件 100 MB · 1 年历史记录", + "cancel": "取消邀请", + "resend": "重新发送", + "vaults": "远程 Vault", + "organization": "组织", + "billing": "管理订阅", + "sharingRequired": "Plus 或自托管服务器支持组织 vault 共享。" + }, + "invitations": { + "organizationRole": "组织角色", + "owner": "所有者", + "admin": "管理员", + "member": "成员", + "pending": "待接受", + "expired": "已过期", + "canceled": "已取消", + "rejected": "已拒绝", + "accepted": "已接受", + "failed": "无法完成请求。", + "signIn": "请登录。", + "title": "组织邀请", + "subtitle": "查看此邀请包含的 Vault 访问权限。", + "missing": "请打开管理员提供的邀请链接。", + "history": "接受邀请并获得密钥批准后,你也可以访问保留的历史记录。", + "keyHelp": "接受后,在所用设备的 Synch Obsidian 插件中打开 Vault 共享与密码,申请管理员批准并设置自己的 Vault 密码。", + "accept": "接受邀请", + "reject": "拒绝邀请", + "next": "邀请已接受。请在 Obsidian 中继续设置密钥。", + "organizations": "管理组织", + "switchAccount": "切换账号", + "wrongAccount": "此账号无法查看邀请。请使用收到邀请的邮箱登录。" } } diff --git a/apps/api/public/i18n/zh-tw.json b/apps/api/public/i18n/zh-tw.json index 77041369..915b622f 100644 --- a/apps/api/public/i18n/zh-tw.json +++ b/apps/api/public/i18n/zh-tw.json @@ -87,7 +87,7 @@ "createNameLabel": "Vault 名稱", "createPasswordLabel": "Vault 密碼", "createConfirmPasswordLabel": "確認 vault 密碼", - "createPasswordHint": "密碼無法復原,請妥善保管。在 Obsidian 連接此 vault 時需要輸入相同的密碼。", + "createPasswordHint": "請妥善保管密碼。遺失後,須由仍持有 vault 金鑰的其他 vault 管理員批准才能復原。", "createConfirm": "建立 vault", "creating": "建立中...", "createdVault": "{name} 已建立。請在 Obsidian 使用相同的 vault 密碼連接。", @@ -132,6 +132,85 @@ "queuedForDeletion": "{name} 已加入刪除佇列。", "unknown": "未知", "created": "建立於 {date}", - "deletionStatus": "刪除 {status}" + "deletionStatus": "刪除 {status}", + "organization": "組織", + "organizations": "管理組織" + }, + "organizations": { + "title": "組織管理", + "subtitle": "管理成員、邀請以及加密 Vault 的存取權限。", + "name": "組織名稱", + "rename": "重新命名", + "organizationRole": "組織角色", + "role": "角色", + "email": "電子郵件地址", + "invite": "邀請成員", + "inviteHelp": "選擇此成員可以存取和編輯的保管庫。擁有者和管理員可以存取和管理所有保管庫。待處理的邀請也會占用成員名額。", + "selectVault": "請至少選擇一個 Vault。", + "sent": "邀請郵件已傳送。", + "copyLink": "複製此邀請連結並傳送給受邀人。對方必須使用受邀的電子郵件地址登入。", + "inviteLink": "邀請連結", + "invitations": "邀請", + "members": "成員", + "remove": "移除成員", + "revoke": "撤銷存取", + "grant": "授予存取", + "leave": "退出組織", + "removeConfirm": "停止此人的同步存取?已下載到裝置上的檔案仍會保留。", + "pendingRefresh": "存取權限已撤銷,正在關閉現有連線。請重新整理以確認。", + "noAccess": "無存取權限", + "yourAccess": "我的權限", + "owner": "擁有者", + "admin": "管理員", + "member": "成員", + "active": "已啟用", + "pending_key": "等待金鑰設定", + "revoked": "已撤銷", + "pending": "待接受", + "expired": "已過期", + "canceled": "已取消", + "rejected": "已拒絕", + "accepted": "已接受", + "refresh": "重新整理", + "working": "儲存中…", + "saved": "已儲存。", + "failed": "無法完成請求。", + "signIn": "請登入。", + "loaded": "組織已載入。", + "noOrganizations": "沒有組織。", + "noVaults": "沒有可用的 Vault。請在遠端 Vault 中建立,或向管理員申請存取。", + "suspended": "共享同步已暫停。資料會保留,續訂 Plus 後將恢復存取。", + "keyHelp": "在 Obsidian 的 Synch → Vault 共享與密碼中申請或核准存取,並設定個人 Vault 密碼。保留的歷史紀錄也會共享。", + "plusLimits": "Plus:含擁有者共 3 人 · 3 個 Vault · 每個 Vault 2 GB · 每個檔案 100 MB · 1 年歷史紀錄", + "cancel": "取消邀請", + "resend": "重新傳送", + "vaults": "遠端 Vault", + "organization": "組織", + "billing": "管理訂閱", + "sharingRequired": "Plus 或自架伺服器支援組織 vault 共享。" + }, + "invitations": { + "organizationRole": "組織角色", + "owner": "擁有者", + "admin": "管理員", + "member": "成員", + "pending": "待接受", + "expired": "已過期", + "canceled": "已取消", + "rejected": "已拒絕", + "accepted": "已接受", + "failed": "無法完成請求。", + "signIn": "請登入。", + "title": "組織邀請", + "subtitle": "查看此邀請包含的 Vault 存取權限。", + "missing": "請開啟管理員提供的邀請連結。", + "history": "接受邀請並取得金鑰核准後,你也可以存取保留的歷史紀錄。", + "keyHelp": "接受後,在使用裝置的 Synch Obsidian 外掛中開啟 Vault 共享與密碼,申請管理員核准並設定自己的 Vault 密碼。", + "accept": "接受邀請", + "reject": "拒絕邀請", + "next": "邀請已接受。請在 Obsidian 中繼續設定金鑰。", + "organizations": "管理組織", + "switchAccount": "切換帳號", + "wrongAccount": "此帳號無法查看邀請。請使用收到邀請的信箱登入。" } } diff --git a/apps/api/public/invitations.html b/apps/api/public/invitations.html new file mode 100644 index 00000000..9a5f16e9 --- /dev/null +++ b/apps/api/public/invitations.html @@ -0,0 +1,93 @@ + + + + + + Synch invitation + + + + + +
+ +

Organization invitation

Review the vault access included with your invitation.

+ +

…

+
+
+ + + diff --git a/apps/api/public/organization-ui.js b/apps/api/public/organization-ui.js new file mode 100644 index 00000000..f684b866 --- /dev/null +++ b/apps/api/public/organization-ui.js @@ -0,0 +1,6 @@ +// Organization management depends on role; sharing actions check plan entitlement. +window.synchOrganizationUI = { + canManage(organization) { + return ["owner", "admin"].includes(organization?.role); + }, +}; diff --git a/apps/api/public/organizations.html b/apps/api/public/organizations.html new file mode 100644 index 00000000..bb79e32a --- /dev/null +++ b/apps/api/public/organizations.html @@ -0,0 +1,211 @@ + + + + + + Synch organizations + + + + + + +
+ + + +

…

+
+
+ + + diff --git a/apps/api/public/styles.css b/apps/api/public/styles.css index ae8837cc..dc6d42a1 100644 --- a/apps/api/public/styles.css +++ b/apps/api/public/styles.css @@ -742,3 +742,86 @@ dialog::backdrop { width: 480px; } } + +/* Organization management keeps actions beside their scope on wide screens. */ +.org-toolbar, .org-inline, .org-row { display: flex; align-items: end; gap: 0.75rem; flex-wrap: wrap; } +.org-toolbar { margin: 1.5rem 0; align-items: center; } +.org-toolbar .input { width: auto; min-width: 12rem; flex: 1; } +.org-detail { display: grid; gap: 1.25rem; margin-top: 1.25rem; } +.org-panel { border: 1px solid var(--zinc-800); border-radius: 0.75rem; padding: 1.5rem; display: grid; gap: 1rem; } +.org-heading { font-size: 1.125rem; font-weight: 600; color: var(--zinc-100); line-height: 1.5; } +.org-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; } +.org-form p { grid-column: 1 / -1; } +.org-field { display: grid; gap: 0.5rem; flex: 1; min-width: 10rem; } +.org-person { flex: 1; min-width: 12rem; overflow-wrap: anywhere; } +.org-row { align-items: center; padding: 0.75rem 0; border-bottom: 1px solid var(--zinc-800); } +.org-row .input, .org-inline > .input { width: auto; } +.org-warning { color: #fbbf24; } +.org-panel ul { padding-left: 1.25rem; } +@media (max-width: 600px) { .org-form { grid-template-columns: 1fr; } .org-panel { padding: 1rem; } .org-row .input { flex: 1; } } + +.organization-topbar { justify-content: space-between; gap: 1rem; flex-wrap: wrap; } + +/* Organization settings follow the document order at every viewport width. */ +.organizations-page { background: #0d0e10; font-size: 1rem; line-height: 1.6; } +.organization-page { max-width: 50rem; padding-block: 1.5rem 4rem; } +.organization-page .organization-topbar { margin-bottom: 1.75rem; padding-bottom: 1rem; border-bottom: 1px solid var(--zinc-800); } +.organization-page .brand { font-size: 0.875rem; line-height: 1.5; font-weight: 650; letter-spacing: 0.14em; } +.organization-page .vaults-header { margin-bottom: 1.5rem; } +.organization-page .page-title { font-size: 1.875rem; font-weight: 600; line-height: 1.3; } +.organization-page .vaults-subtitle { font-size: 1rem; color: var(--zinc-400); } +.organization-page .org-toolbar { margin: 0; padding: 0.75rem 0; } +.organization-page .org-toolbar .input { flex: 0 1 16rem; min-width: 0; } +.organization-page #vaults-link { margin-left: auto; font-size: 1rem; color: var(--zinc-300); } +.organization-page #vaults-link::after, .organization-page .org-billing::after { content: ' ↗'; color: var(--zinc-500); } +.organization-page #status { font-size: 0.9375rem; } +.organization-page #status:empty { display: none; } +.organization-page #status[data-kind="error"] { color: var(--red-400); } +.organization-page .org-detail { grid-template-columns: minmax(0, 1fr); gap: 0; margin-top: 0.75rem; } +.organization-page .org-panel { background: transparent; border: 0; border-top: 1px solid #2a2b30; border-radius: 0; padding: 1.5rem 0; gap: 1rem; align-content: start; min-width: 0; } +.organization-page .org-heading { font-size: 1.25rem; font-weight: 600; letter-spacing: -0.02em; } +.organization-page .org-summary { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.75rem 1.5rem; border-top: 0; padding: 0 0 1.5rem; } +.organization-page .org-summary .org-warning { flex-basis: 100%; } +.organization-page .org-summary > p { font-size: 0.9375rem; line-height: 1.7; } +.organization-page .org-billing { justify-self: start; font-size: 0.9375rem; white-space: nowrap; } +.organization-page .org-settings { flex: 1; font-size: 0.9375rem; } +.organization-page .org-settings summary { cursor: pointer; width: fit-content; } +.organization-page .org-settings form { margin-top: 1rem; max-width: 34rem; } +.organization-page .org-panel-heading { display: flex; align-items: center; gap: 0.5rem; } +.organization-page .org-count { padding: 0.0625rem 0.4375rem; border-radius: 0.375rem; background: #2a2b30; color: var(--zinc-300); font-size: 0.875rem; } +.organization-page .org-row { padding: 0.875rem 0; gap: 0.75rem; } +.organization-page .org-row:last-child { border-bottom: 0; padding-bottom: 0; } +.organization-page .org-person { display: flex; align-items: center; gap: 0.75rem; min-width: 0; flex-basis: 12rem; } +.organization-page .org-person-info { display: grid; gap: 0.1875rem; min-width: 0; } +.organization-page .org-person-name { font-size: 1rem; color: var(--zinc-200); } +.organization-page .vault-meta { font-size: 0.9375rem; color: #9799a3; word-break: normal; overflow-wrap: anywhere; } +.organization-page .org-invite-disclosure summary { cursor: pointer; color: var(--zinc-200); font-size: 1rem; width: fit-content; } +.organization-page .org-invite-disclosure[open] summary { margin-bottom: 1.25rem; } +.organization-page .org-role { font-size: 0.9375rem; color: var(--zinc-400); } +.organization-page .org-form { grid-template-columns: minmax(0, 1fr); gap: 1rem; } +.organization-page .org-form > .btn { grid-column: 1 / -1; justify-self: start; min-width: 8rem; margin-top: 0.25rem; } +.organization-page .org-field { min-width: 0; } +.organization-page .label { font-size: 0.9375rem; line-height: 1.5; } +.organization-page .org-form > p { line-height: 1.7; font-size: 0.9375rem; padding: 0; max-width: 40rem; } +.organization-page .input { font-family: inherit; font-size: 1rem; border-radius: 0.5rem; min-height: 2.75rem; background-color: #101114; border-color: #35363d; } +.organization-page .input:disabled { opacity: 0.65; } +.organization-page .btn { font-size: 0.9375rem; line-height: 1.5; border-radius: 0.5rem; min-height: 2.75rem; } +.organization-page :is(a, button, summary, input, select):focus-visible { outline: 2px solid #b2b5cd; outline-offset: 3px; } +.organization-page .org-list-title { font-size: 0.9375rem; font-weight: 500; padding-top: 1rem; border-top: 1px solid var(--zinc-800); color: var(--zinc-300); } +.organization-page .org-vaults { display: grid; gap: 0.875rem; padding-top: 1.5rem; border-top: 1px solid #2a2b30; } +.organization-page .org-section-title { color: var(--zinc-200); font-size: 1.25rem; font-weight: 600; margin-top: 0.25rem; } +.organization-page .org-help { font-size: 0.9375rem; line-height: 1.75; color: #9799a3; max-width: 55rem; margin-bottom: 0.375rem; } +.organization-page .org-vault { gap: 0.375rem; padding: 1rem 1.25rem; border: 1px solid #2a2b30; border-radius: 0.5rem; background: #141518; } +.organization-page .org-vault > .org-inline { margin-top: 1rem; } +.organization-page #invite-result { margin-top: 1rem; } +@media (max-width: 480px) { + .organization-page { padding-inline: 1rem; padding-top: 1rem; } + .organization-page .organization-topbar { margin-bottom: 2rem; } + .organization-page .org-vault { padding: 1rem; } + .organization-page .org-toolbar .label { width: 100%; } + .organization-page .org-toolbar .input { flex: 1; } + .organization-page #vaults-link { width: 100%; margin-left: 0; } + .organization-page .org-form { grid-template-columns: 1fr; } + .organization-page .org-row > .input { max-width: 100%; } + .organization-page .org-inline > .input { width: 100%; } +} diff --git a/apps/api/public/vault-crypto.js b/apps/api/public/vault-crypto.js index 8318572f..5d769f30 100644 --- a/apps/api/public/vault-crypto.js +++ b/apps/api/public/vault-crypto.js @@ -1,4 +1,4 @@ -"use strict";var synchVaultCrypto=(()=>{var EA=Object.create;var x=Object.defineProperty;var fA=Object.getOwnPropertyDescriptor;var DA=Object.getOwnPropertyNames;var FA=Object.getPrototypeOf,cA=Object.prototype.hasOwnProperty;var kA=(I,i)=>()=>{try{return i||I((i={exports:{}}).exports,i),i.exports}catch(r){throw i=0,r}},pA=(I,i)=>{for(var r in i)x(I,r,{get:i[r],enumerable:!0})},rA=(I,i,r,a)=>{if(i&&typeof i=="object"||typeof i=="function")for(let F of DA(i))!cA.call(I,F)&&F!==r&&x(I,F,{get:()=>i[F],enumerable:!(a=fA(i,F))||a.enumerable});return I};var SA=(I,i,r)=>(r=I!=null?EA(FA(I)):{},rA(i||!I||!I.__esModule?x(r,"default",{value:I,enumerable:!0}):r,I)),UA=I=>rA(x({},"__esModule",{value:!0}),I);var BA=kA((v,oA)=>{(function(I,i){typeof v=="object"&&typeof oA<"u"?i(v):typeof define=="function"&&define.amd?define(["exports"],i):i((I=typeof globalThis<"u"?globalThis:I||self).hashwasm=I.hashwasm||{})})(v,(function(I){"use strict";function i(A,C,g,e){return new(g||(g=Promise))((function(t,o){function h(s){try{B(e.next(s))}catch(D){o(D)}}function n(s){try{B(e.throw(s))}catch(D){o(D)}}function B(s){var D;s.done?t(s.value):(D=s.value,D instanceof g?D:new g((function(f){f(D)}))).then(h,n)}B((e=e.apply(A,C||[])).next())}))}typeof SuppressedError=="function"&&SuppressedError;var r,a={name:"argon2",data:"AGFzbQEAAAABKQVgAX8Bf2AAAX9gEH9/f39/f39/f39/f39/f38AYAR/f39/AGACf38AAwYFAAECAwQFBgEBAoCAAgYIAX8BQZCoBAsHQQQGbWVtb3J5AgASSGFzaF9TZXRNZW1vcnlTaXplAAAOSGFzaF9HZXRCdWZmZXIAAQ5IYXNoX0NhbGN1bGF0ZQAECvEyBVgBAn9BACEBAkAgAEEAKAKICCICRg0AAkAgACACayIAQRB2IABBgIB8cSAASWoiAEAAQX9HDQBB/wHADwtBACEBQQBBACkDiAggAEEQdK18NwOICAsgAcALcAECfwJAQQAoAoAIIgANAEEAPwBBEHQiADYCgAhBACgCiAgiAUGAgCBGDQACQEGAgCAgAWsiAEEQdiAAQYCAfHEgAElqIgBAAEF/Rw0AQQAPC0EAQQApA4gIIABBEHStfDcDiAhBACgCgAghAAsgAAvcDgECfiAAIAQpAwAiECAAKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAMIBAgDCkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgBCAQIAQpAwCFQiiJIhA3AwAgACAQIAApAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAwgECAMKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAEIBAgBCkDAIVCAYk3AwAgASAFKQMAIhAgASkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDSAQIA0pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAEgECABKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACANIBAgDSkDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAIgBikDACIQIAIpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIA4gECAOKQMAhUIgiSIQNwMAIAogECAKKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACACIBAgAikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDiAQIA4pAwCFQjCJIhA3AwAgCiAQIAopAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACADIAcpAwAiECADKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAPIBAgDykDAIVCIIkiEDcDACALIBAgCykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAyAQIAMpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA8gECAPKQMAhUIwiSIQNwMAIAsgECALKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgACAFKQMAIhAgACkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDyAQIA8pAwCFQiCJIhA3AwAgCiAQIAopAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAAgECAAKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAPIBAgDykDAIVCMIkiEDcDACAKIBAgCikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAEgBikDACIQIAEpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAwgECAMKQMAhUIgiSIQNwMAIAsgECALKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACABIBAgASkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDCAQIAwpAwCFQjCJIhA3AwAgCyAQIAspAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACACIAcpAwAiECACKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACANIBAgDSkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAiAQIAIpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA0gECANKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgAyAEKQMAIhAgAykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDiAQIA4pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAQgECAEKQMAhUIoiSIQNwMAIAMgECADKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAOIBAgDikDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBCAQIAQpAwCFQgGJNwMAC98aAQN/QQAhBEEAIAIpAwAgASkDAIU3A5AIQQAgAikDCCABKQMIhTcDmAhBACACKQMQIAEpAxCFNwOgCEEAIAIpAxggASkDGIU3A6gIQQAgAikDICABKQMghTcDsAhBACACKQMoIAEpAyiFNwO4CEEAIAIpAzAgASkDMIU3A8AIQQAgAikDOCABKQM4hTcDyAhBACACKQNAIAEpA0CFNwPQCEEAIAIpA0ggASkDSIU3A9gIQQAgAikDUCABKQNQhTcD4AhBACACKQNYIAEpA1iFNwPoCEEAIAIpA2AgASkDYIU3A/AIQQAgAikDaCABKQNohTcD+AhBACACKQNwIAEpA3CFNwOACUEAIAIpA3ggASkDeIU3A4gJQQAgAikDgAEgASkDgAGFNwOQCUEAIAIpA4gBIAEpA4gBhTcDmAlBACACKQOQASABKQOQAYU3A6AJQQAgAikDmAEgASkDmAGFNwOoCUEAIAIpA6ABIAEpA6ABhTcDsAlBACACKQOoASABKQOoAYU3A7gJQQAgAikDsAEgASkDsAGFNwPACUEAIAIpA7gBIAEpA7gBhTcDyAlBACACKQPAASABKQPAAYU3A9AJQQAgAikDyAEgASkD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",hash:"e4cdc523"};class F{constructor(){this.mutex=Promise.resolve()}lock(){let C=()=>{};return this.mutex=this.mutex.then((()=>new Promise(C))),new Promise((g=>{C=g}))}dispatch(C){return i(this,void 0,void 0,(function*(){let g=yield this.lock();try{return yield Promise.resolve(C())}finally{g()}}))}}let J=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global,d=(r=J.Buffer)!==null&&r!==void 0?r:null,Y=J.TextEncoder?new J.TextEncoder:null;function z(A,C){return(15&A)+(A>>6|A>>3&8)<<4|(15&C)+(C>>6|C>>3&8)}function $(A,C){let g=C.length>>1;for(let e=0;e>>4;A[e++]=o>9?o+AA:o+IA,o=15&C[t],A[e++]=o>9?o+AA:o+IA}return String.fromCharCode.apply(null,A)}let l=d!==null?A=>{if(typeof A=="string"){let C=d.from(A,"utf8");return new Uint8Array(C.buffer,C.byteOffset,C.length)}if(d.isBuffer(A))return new Uint8Array(A.buffer,A.byteOffset,A.length);if(ArrayBuffer.isView(A))return new Uint8Array(A.buffer,A.byteOffset,A.byteLength);throw new Error("Invalid data type!")}:A=>{if(typeof A=="string")return Y.encode(A);if(ArrayBuffer.isView(A))return new Uint8Array(A.buffer,A.byteOffset,A.byteLength);throw new Error("Invalid data type!")},U="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",N=new Uint8Array(256);for(let A=0;A>18&63)+U.charAt(n>>12&63)+U.charAt(n>>6&63)+U.charAt(63&n);t.push(B)}if(e===1){let h=A[g-1],n=U.charAt(h>>2),B=U.charAt(h<<4&63);t.push(`${n}${B}`),C&&t.push("==")}else if(e===2){let h=(A[g-2]<<8)+A[g-1],n=U.charAt(h>>10),B=U.charAt(h>>4&63),s=U.charAt(h<<2&63);t.push(`${n}${B}${s}`),C&&t.push("=")}return t.join("")}function gA(A){let C=Math.floor(.75*A.length),g=A.length;return A[g-1]==="="&&(C-=1,A[g-2]==="="&&(C-=1)),C}function CA(A){let C=gA(A),g=A.length,e=new Uint8Array(C),t=0;for(let o=0;o>4,t+=1,e[t]=(15&n)<<4|B>>2,t+=1,e[t]=(3&B)<<6|63&s,t+=1}return e}let L=16384,aA=new F,Z=new Map;function eA(A,C){return i(this,void 0,void 0,(function*(){let g=null,e=null,t=!1;if(typeof WebAssembly>"u")throw new Error("WebAssembly is not supported in this environment!");let o=()=>new DataView(g.exports.memory.buffer).getUint32(g.exports.STATE_SIZE,!0),h=aA.dispatch((()=>i(this,void 0,void 0,(function*(){if(!Z.has(A.name)){let w=CA(A.data),E=WebAssembly.compile(w);Z.set(A.name,E)}let Q=yield Z.get(A.name);g=yield WebAssembly.instantiate(Q,{})})))),n=(Q=null)=>{t=!0,g.exports.Hash_Init(Q)},B=Q=>{if(!t)throw new Error("update() called before init()");(w=>{let E=0;for(;E{if(!t)throw new Error("digest() called before init()");return t=!1,g.exports.Hash_Final(w),Q==="binary"?e.slice(0,C):T(s,e,C)},f=Q=>typeof Q=="string"?Q.length<4096:Q.byteLength!0;break;case"blake2b":case"blake2s":k=(Q,w)=>w<=512&&f(Q);break;case"blake3":k=(Q,w)=>w===0&&f(Q);break;case"xxhash64":case"xxhash3":case"xxhash128":case"crc64":k=()=>!1}return yield i(this,void 0,void 0,(function*(){g||(yield h);let Q=g.exports.Hash_GetBuffer(),w=g.exports.memory.buffer;e=new Uint8Array(w,Q,L)})),{getMemory:()=>e,writeMemory:(Q,w=0)=>{e.set(Q,w)},getExports:()=>g.exports,setMemorySize:Q=>{g.exports.Hash_SetMemorySize(Q);let w=g.exports.Hash_GetBuffer(),E=g.exports.memory.buffer;e=new Uint8Array(E,w,Q)},init:n,update:B,digest:D,save:()=>{if(!t)throw new Error("save() can only be called after init() and before digest()");let Q=g.exports.Hash_GetState(),w=o(),E=g.exports.memory.buffer,c=new Uint8Array(E,Q,w),G=new Uint8Array(4+w);return $(G,A.hash),G.set(c,4),G},load:Q=>{if(!(Q instanceof Uint8Array))throw new Error("load() expects an Uint8Array generated by save()");let w=g.exports.Hash_GetState(),E=o(),c=4+E,G=g.exports.memory.buffer;if(Q.length!==c)throw new Error(`Bad state length (expected ${c} bytes, got ${Q.length})`);if(!(function(p,S){if(p.length!==2*S.length)return!1;for(let y=0;y{if(!k(Q,w))return n(w),B(Q),D("hex",E);let c=l(Q);return e.set(c),g.exports.Hash_Calculate(c.length,w,E),T(s,e,C)},hashLength:C}}))}var sA={name:"blake2b",data:"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",hash:"c6f286e6"};function tA(A){return!Number.isInteger(A)||A<8||A>512||A%8!=0?new Error("Invalid variant! Valid values: 8, 16, ..., 512"):null}function W(A=512,C=null){if(tA(A))return Promise.reject(tA(A));let g=null,e=A;if(C!==null){if(g=l(C),g.length>64)return Promise.reject(new Error("Max key length is 64 bytes"));t=A,o=g.length,e=t|o<<16}var t,o;let h=A/8;return eA(sA,h).then((n=>{e>512&&n.writeMemory(g),n.init(e);let B={init:e>512?()=>(n.writeMemory(g),n.init(e),B):()=>(n.init(e),B),update:s=>(n.update(s),B),digest:s=>n.digest(s),save:()=>n.save(),load:s=>(n.load(s),B),blockSize:128,digestSize:h};return B}))}new F;let QA=new DataView(new ArrayBuffer(4));function u(A){return QA.setInt32(0,A,!0),new Uint8Array(QA.buffer)}function q(A,C,g){return i(this,void 0,void 0,(function*(){if(g<=64){let B=yield W(8*g);return B.update(u(g)),B.update(C),B.digest("binary")}let e=Math.ceil(g/32)-2,t=new Uint8Array(g);A.init(),A.update(u(g)),A.update(C);let o=A.digest("binary");t.set(o.subarray(0,32),0);for(let B=1;B{var C;if(!A||typeof A!="object")throw new Error("Invalid options parameter. It requires an object.");if(!A.password)throw new Error("Password must be specified");if(A.password=l(A.password),A.password.length<1)throw new Error("Password must be specified");if(!A.salt)throw new Error("Salt must be specified");if(A.salt=l(A.salt),A.salt.length<8)throw new Error("Salt should be at least 8 bytes long");if(A.secret=l((C=A.secret)!==null&&C!==void 0?C:""),!Number.isInteger(A.iterations)||A.iterations<1)throw new Error("Iterations should be a positive number");if(!Number.isInteger(A.parallelism)||A.parallelism<1)throw new Error("Parallelism should be a positive number");if(!Number.isInteger(A.hashLength)||A.hashLength<4)throw new Error("Hash length should be at least 4 bytes.");if(!Number.isInteger(A.memorySize))throw new Error("Memory size should be specified.");if(A.memorySize<8*A.parallelism)throw new Error("Memory size should be at least 8 * parallelism.");if(A.outputType===void 0&&(A.outputType="hex"),!["hex","binary","encoded"].includes(A.outputType))throw new Error(`Insupported output type ${A.outputType}. Valid values: ['hex', 'binary', 'encoded']`)};I.argon2Verify=function(A){return i(this,void 0,void 0,(function*(){(e=>{if(!e||typeof e!="object")throw new Error("Invalid options parameter. It requires an object.");if(e.hash===void 0||typeof e.hash!="string")throw new Error("Hash should be specified")})(A);let C=((e,t,o)=>{let h=t.match(/^\$argon2(id|i|d)\$v=([0-9]+)\$((?:[mtp]=[0-9]+,){2}[mtp]=[0-9]+)\$([A-Za-z0-9+/]+)\$([A-Za-z0-9+/]+)$/);if(!h)throw new Error("Invalid hash");let[,n,B,s,D,f]=h;if(B!=="19")throw new Error(`Unsupported version: ${B}`);let k={},Q={m:"memorySize",p:"parallelism",t:"iterations"};for(let w of s.split(",")){let[E,c]=w.split("=");k[Q[E]]=Number(c)}return Object.assign(Object.assign({},k),{password:e,secret:o,hashType:n,salt:CA(D),hashLength:gA(f),outputType:"encoded"})})(A.password,A.hash,A.secret);M(C);let g=A.hash.lastIndexOf("$")+1;return(yield b(C)).substring(g)===A.hash.substring(g)}))},I.argon2d=function(A){return i(this,void 0,void 0,(function*(){return M(A),b(Object.assign(Object.assign({},A),{hashType:"d"}))}))},I.argon2i=function(A){return i(this,void 0,void 0,(function*(){return M(A),b(Object.assign(Object.assign({},A),{hashType:"i"}))}))},I.argon2id=function(A){return i(this,void 0,void 0,(function*(){return M(A),b(Object.assign(Object.assign({},A),{hashType:"id"}))}))}}))});var MA={};pA(MA,{VaultPasswordError:()=>P,createArgon2idMetadata:()=>j,createPasswordWrappedRemoteVaultKey:()=>KA,decodeBase64:()=>H,deriveWrapKey:()=>R,encodeBase64:()=>V,randomBytes:()=>m,toArrayBuffer:()=>K,unwrapRemoteVaultKeyWithPassword:()=>JA,validateVaultPassword:()=>NA});function m(I){return crypto.getRandomValues(new Uint8Array(I))}function V(I){let i=[];for(let r=0;rSA(BA(),1)),a=r.default?.argon2id??r["module.exports"]?.argon2id;if(!a)throw new Error("argon2id module failed to load");let F=await a({password:new TextEncoder().encode(I),salt:H(i.salt),iterations:i.iterations,parallelism:i.parallelism,memorySize:i.memoryKiB,hashLength:lA,outputType:"binary"});return await crypto.subtle.importKey("raw",K(F),{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}var nA="aes-256-gcm",hA=1,uA=1,dA=32,GA=12,P=class extends Error{constructor(r,a){super(a);this.code=r;this.name="VaultPasswordError"}};async function KA(I,i={}){let r=wA(I),a=m(dA),F=j(i.kdfOverrides),J=await R(r,F),d=m(GA),Y=await VA(J,a,d);return{remoteVaultKey:a,envelope:{version:hA,keyVersion:uA,kdf:F,wrap:{algorithm:nA,nonce:V(d),ciphertext:V(Y)}}}}async function JA(I,i){let r=wA(I);HA(i);let a=H(i.kdf.salt),F=H(i.wrap.nonce),J=H(i.wrap.ciphertext),d=await R(r,{...i.kdf,salt:V(a)}),Y=await crypto.subtle.decrypt({name:"AES-GCM",iv:K(F)},d,K(J));return new Uint8Array(Y)}async function VA(I,i,r){let a=await crypto.subtle.encrypt({name:"AES-GCM",iv:K(r)},I,K(i));return new Uint8Array(a)}function HA(I){if(I.version!==hA)throw new Error(`unsupported wrapper version: ${I.version}`);if(I.wrap.algorithm!==nA)throw new Error(`unsupported wrap algorithm: ${I.wrap.algorithm}`)}function wA(I){if(!I)throw new P("required","Password is required.");if(I!==I.trim())throw new P("outer_spaces","Password cannot start or end with spaces.");return I}var mA=new Set(["123456","123456789","1234567890","password","password1","password123","qwerty","qwerty123","letmein","admin","welcome","iloveyou","vault","vaultpassword","synch","synchpassword","obsidian","obsidianvault","obsidianvaultpassword","synchvaultpassword"]),YA=["password","qwerty","letmein","admin","welcome","iloveyou","vault","synch","obsidian"];function NA(I){return I?I!==I.trim()?{ok:!1,code:"outer_spaces",message:"Password cannot start or end with spaces."}:I.length<12?{ok:!1,code:"min_length",count:12,message:"Password must be at least 12 characters."}:I.length>256?{ok:!1,code:"max_length",count:256,message:"Password must be 256 characters or fewer."}:PA(I)?{ok:!1,code:"too_weak",message:"Password is too easy to guess. Use a longer passphrase."}:OA(I)?{ok:!1,code:"repeated_character",message:"Password cannot be one repeated character."}:bA(I)?{ok:!1,code:"simple_sequence",message:"Password cannot be a simple sequence."}:{ok:!0}:{ok:!1,code:"required",message:"Password is required."}}function OA(I){return new Set(I.toLowerCase()).size===1}function PA(I){let i=I.toLowerCase().replace(/[^a-z0-9]/g,"");if(mA.has(i))return!0;for(let r of YA)i=i.split(r).join("");return i===""||/^[0-9]+$/.test(i)}function bA(I){if(!/^[a-z]+$/i.test(I)&&!/^[0-9]+$/.test(I))return!1;let i=I.toLowerCase(),r=i.charCodeAt(1)-i.charCodeAt(0);if(r!==1&&r!==-1)return!1;for(let a=1;a{var kA=Object.create;var v=Object.defineProperty;var uA=Object.getOwnPropertyDescriptor;var SA=Object.getOwnPropertyNames;var lA=Object.getPrototypeOf,dA=Object.prototype.hasOwnProperty;var UA=(I,i)=>()=>{try{return i||I((i={exports:{}}).exports,i),i.exports}catch(g){throw i=0,g}},GA=(I,i)=>{for(var g in i)v(I,g,{get:i[g],enumerable:!0})},BA=(I,i,g,B)=>{if(i&&typeof i=="object"||typeof i=="function")for(let E of SA(i))!dA.call(I,E)&&E!==g&&v(I,E,{get:()=>i[E],enumerable:!(B=uA(i,E))||B.enumerable});return I};var KA=(I,i,g)=>(g=I!=null?kA(lA(I)):{},BA(i||!I||!I.__esModule?v(g,"default",{value:I,enumerable:!0}):g,I)),mA=I=>BA(v({},"__esModule",{value:!0}),I);var sA=UA((X,hA)=>{(function(I,i){typeof X=="object"&&typeof hA<"u"?i(X):typeof define=="function"&&define.amd?define(["exports"],i):i((I=typeof globalThis<"u"?globalThis:I||self).hashwasm=I.hashwasm||{})})(X,(function(I){"use strict";function i(A,t,e,r){return new(e||(e=Promise))((function(C,o){function h(w){try{Q(r.next(w))}catch(D){o(D)}}function a(w){try{Q(r.throw(w))}catch(D){o(D)}}function Q(w){var D;w.done?C(w.value):(D=w.value,D instanceof e?D:new e((function(c){c(D)}))).then(h,a)}Q((r=r.apply(A,t||[])).next())}))}typeof SuppressedError=="function"&&SuppressedError;var g,B={name:"argon2",data:"AGFzbQEAAAABKQVgAX8Bf2AAAX9gEH9/f39/f39/f39/f39/f38AYAR/f39/AGACf38AAwYFAAECAwQFBgEBAoCAAgYIAX8BQZCoBAsHQQQGbWVtb3J5AgASSGFzaF9TZXRNZW1vcnlTaXplAAAOSGFzaF9HZXRCdWZmZXIAAQ5IYXNoX0NhbGN1bGF0ZQAECvEyBVgBAn9BACEBAkAgAEEAKAKICCICRg0AAkAgACACayIAQRB2IABBgIB8cSAASWoiAEAAQX9HDQBB/wHADwtBACEBQQBBACkDiAggAEEQdK18NwOICAsgAcALcAECfwJAQQAoAoAIIgANAEEAPwBBEHQiADYCgAhBACgCiAgiAUGAgCBGDQACQEGAgCAgAWsiAEEQdiAAQYCAfHEgAElqIgBAAEF/Rw0AQQAPC0EAQQApA4gIIABBEHStfDcDiAhBACgCgAghAAsgAAvcDgECfiAAIAQpAwAiECAAKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAMIBAgDCkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgBCAQIAQpAwCFQiiJIhA3AwAgACAQIAApAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAwgECAMKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAEIBAgBCkDAIVCAYk3AwAgASAFKQMAIhAgASkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDSAQIA0pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAEgECABKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACANIBAgDSkDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAIgBikDACIQIAIpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIA4gECAOKQMAhUIgiSIQNwMAIAogECAKKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACACIBAgAikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDiAQIA4pAwCFQjCJIhA3AwAgCiAQIAopAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACADIAcpAwAiECADKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAPIBAgDykDAIVCIIkiEDcDACALIBAgCykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAyAQIAMpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA8gECAPKQMAhUIwiSIQNwMAIAsgECALKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgACAFKQMAIhAgACkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDyAQIA8pAwCFQiCJIhA3AwAgCiAQIAopAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAAgECAAKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAPIBAgDykDAIVCMIkiEDcDACAKIBAgCikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAEgBikDACIQIAEpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAwgECAMKQMAhUIgiSIQNwMAIAsgECALKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACABIBAgASkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDCAQIAwpAwCFQjCJIhA3AwAgCyAQIAspAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACACIAcpAwAiECACKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACANIBAgDSkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAiAQIAIpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA0gECANKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgAyAEKQMAIhAgAykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDiAQIA4pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAQgECAEKQMAhUIoiSIQNwMAIAMgECADKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAOIBAgDikDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBCAQIAQpAwCFQgGJNwMAC98aAQN/QQAhBEEAIAIpAwAgASkDAIU3A5AIQQAgAikDCCABKQMIhTcDmAhBACACKQMQIAEpAxCFNwOgCEEAIAIpAxggASkDGIU3A6gIQQAgAikDICABKQMghTcDsAhBACACKQMoIAEpAyiFNwO4CEEAIAIpAzAgASkDMIU3A8AIQQAgAikDOCABKQM4hTcDyAhBACACKQNAIAEpA0CFNwPQCEEAIAIpA0ggASkDSIU3A9gIQQAgAikDUCABKQNQhTcD4AhBACACKQNYIAEpA1iFNwPoCEEAIAIpA2AgASkDYIU3A/AIQQAgAikDaCABKQNohTcD+AhBACACKQNwIAEpA3CFNwOACUEAIAIpA3ggASkDeIU3A4gJQQAgAikDgAEgASkDgAGFNwOQCUEAIAIpA4gBIAEpA4gBhTcDmAlBACACKQOQASABKQOQAYU3A6AJQQAgAikDmAEgASkDmAGFNwOoCUEAIAIpA6ABIAEpA6ABhTcDsAlBACACKQOoASABKQOoAYU3A7gJQQAgAikDsAEgASkDsAGFNwPACUEAIAIpA7gBIAEpA7gBhTcDyAlBACACKQPAASABKQPAAYU3A9AJQQAgAikDyAEgASkD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",hash:"e4cdc523"};class E{constructor(){this.mutex=Promise.resolve()}lock(){let t=()=>{};return this.mutex=this.mutex.then((()=>new Promise(t))),new Promise((e=>{t=e}))}dispatch(t){return i(this,void 0,void 0,(function*(){let e=yield this.lock();try{return yield Promise.resolve(t())}finally{e()}}))}}let U=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global,K=(g=U.Buffer)!==null&&g!==void 0?g:null,T=U.TextEncoder?new U.TextEncoder:null;function P(A,t){return(15&A)+(A>>6|A>>3&8)<<4|(15&t)+(t>>6|t>>3&8)}function eA(A,t){let e=t.length>>1;for(let r=0;r>>4;A[r++]=o>9?o+gA:o+tA,o=15&t[C],A[r++]=o>9?o+gA:o+tA}return String.fromCharCode.apply(null,A)}let m=K!==null?A=>{if(typeof A=="string"){let t=K.from(A,"utf8");return new Uint8Array(t.buffer,t.byteOffset,t.length)}if(K.isBuffer(A))return new Uint8Array(A.buffer,A.byteOffset,A.length);if(ArrayBuffer.isView(A))return new Uint8Array(A.buffer,A.byteOffset,A.byteLength);throw new Error("Invalid data type!")}:A=>{if(typeof A=="string")return T.encode(A);if(ArrayBuffer.isView(A))return new Uint8Array(A.buffer,A.byteOffset,A.byteLength);throw new Error("Invalid data type!")},l="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b=new Uint8Array(256);for(let A=0;A>18&63)+l.charAt(a>>12&63)+l.charAt(a>>6&63)+l.charAt(63&a);C.push(Q)}if(r===1){let h=A[e-1],a=l.charAt(h>>2),Q=l.charAt(h<<4&63);C.push(`${a}${Q}`),t&&C.push("==")}else if(r===2){let h=(A[e-2]<<8)+A[e-1],a=l.charAt(h>>10),Q=l.charAt(h>>4&63),w=l.charAt(h<<2&63);C.push(`${a}${Q}${w}`),t&&C.push("=")}return C.join("")}function CA(A){let t=Math.floor(.75*A.length),e=A.length;return A[e-1]==="="&&(t-=1,A[e-2]==="="&&(t-=1)),t}function nA(A){let t=CA(A),e=A.length,r=new Uint8Array(t),C=0;for(let o=0;o>4,C+=1,r[C]=(15&a)<<4|Q>>2,C+=1,r[C]=(3&Q)<<6|63&w,C+=1}return r}let W=16384,FA=new E,Z=new Map;function oA(A,t){return i(this,void 0,void 0,(function*(){let e=null,r=null,C=!1;if(typeof WebAssembly>"u")throw new Error("WebAssembly is not supported in this environment!");let o=()=>new DataView(e.exports.memory.buffer).getUint32(e.exports.STATE_SIZE,!0),h=FA.dispatch((()=>i(this,void 0,void 0,(function*(){if(!Z.has(A.name)){let s=nA(A.data),f=WebAssembly.compile(s);Z.set(A.name,f)}let n=yield Z.get(A.name);e=yield WebAssembly.instantiate(n,{})})))),a=(n=null)=>{C=!0,e.exports.Hash_Init(n)},Q=n=>{if(!C)throw new Error("update() called before init()");(s=>{let f=0;for(;f{if(!C)throw new Error("digest() called before init()");return C=!1,e.exports.Hash_Final(s),n==="binary"?r.slice(0,t):L(w,r,t)},c=n=>typeof n=="string"?n.length<4096:n.byteLength!0;break;case"blake2b":case"blake2s":k=(n,s)=>s<=512&&c(n);break;case"blake3":k=(n,s)=>s===0&&c(n);break;case"xxhash64":case"xxhash3":case"xxhash128":case"crc64":k=()=>!1}return yield i(this,void 0,void 0,(function*(){e||(yield h);let n=e.exports.Hash_GetBuffer(),s=e.exports.memory.buffer;r=new Uint8Array(s,n,W)})),{getMemory:()=>r,writeMemory:(n,s=0)=>{r.set(n,s)},getExports:()=>e.exports,setMemorySize:n=>{e.exports.Hash_SetMemorySize(n);let s=e.exports.Hash_GetBuffer(),f=e.exports.memory.buffer;r=new Uint8Array(f,s,n)},init:a,update:Q,digest:D,save:()=>{if(!C)throw new Error("save() can only be called after init() and before digest()");let n=e.exports.Hash_GetState(),s=o(),f=e.exports.memory.buffer,p=new Uint8Array(f,n,s),J=new Uint8Array(4+s);return eA(J,A.hash),J.set(p,4),J},load:n=>{if(!(n instanceof Uint8Array))throw new Error("load() expects an Uint8Array generated by save()");let s=e.exports.Hash_GetState(),f=o(),p=4+f,J=e.exports.memory.buffer;if(n.length!==p)throw new Error(`Bad state length (expected ${p} bytes, got ${n.length})`);if(!(function(u,S){if(u.length!==2*S.length)return!1;for(let G=0;G{if(!k(n,s))return a(s),Q(n),D("hex",f);let p=m(n);return r.set(p),e.exports.Hash_Calculate(p.length,s,f),L(w,r,t)},hashLength:t}}))}var yA={name:"blake2b",data:"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",hash:"c6f286e6"};function QA(A){return!Number.isInteger(A)||A<8||A>512||A%8!=0?new Error("Invalid variant! Valid values: 8, 16, ..., 512"):null}function q(A=512,t=null){if(QA(A))return Promise.reject(QA(A));let e=null,r=A;if(t!==null){if(e=m(t),e.length>64)return Promise.reject(new Error("Max key length is 64 bytes"));C=A,o=e.length,r=C|o<<16}var C,o;let h=A/8;return oA(yA,h).then((a=>{r>512&&a.writeMemory(e),a.init(r);let Q={init:r>512?()=>(a.writeMemory(e),a.init(r),Q):()=>(a.init(r),Q),update:w=>(a.update(w),Q),digest:w=>a.digest(w),save:()=>a.save(),load:w=>(a.load(w),Q),blockSize:128,digestSize:h};return Q}))}new E;let aA=new DataView(new ArrayBuffer(4));function V(A){return aA.setInt32(0,A,!0),new Uint8Array(aA.buffer)}function _(A,t,e){return i(this,void 0,void 0,(function*(){if(e<=64){let Q=yield q(8*e);return Q.update(V(e)),Q.update(t),Q.digest("binary")}let r=Math.ceil(e/32)-2,C=new Uint8Array(e);A.init(),A.update(V(e)),A.update(t);let o=A.digest("binary");C.set(o.subarray(0,32),0);for(let Q=1;Q{var t;if(!A||typeof A!="object")throw new Error("Invalid options parameter. It requires an object.");if(!A.password)throw new Error("Password must be specified");if(A.password=m(A.password),A.password.length<1)throw new Error("Password must be specified");if(!A.salt)throw new Error("Salt must be specified");if(A.salt=m(A.salt),A.salt.length<8)throw new Error("Salt should be at least 8 bytes long");if(A.secret=m((t=A.secret)!==null&&t!==void 0?t:""),!Number.isInteger(A.iterations)||A.iterations<1)throw new Error("Iterations should be a positive number");if(!Number.isInteger(A.parallelism)||A.parallelism<1)throw new Error("Parallelism should be a positive number");if(!Number.isInteger(A.hashLength)||A.hashLength<4)throw new Error("Hash length should be at least 4 bytes.");if(!Number.isInteger(A.memorySize))throw new Error("Memory size should be specified.");if(A.memorySize<8*A.parallelism)throw new Error("Memory size should be at least 8 * parallelism.");if(A.outputType===void 0&&(A.outputType="hex"),!["hex","binary","encoded"].includes(A.outputType))throw new Error(`Insupported output type ${A.outputType}. Valid values: ['hex', 'binary', 'encoded']`)};I.argon2Verify=function(A){return i(this,void 0,void 0,(function*(){(r=>{if(!r||typeof r!="object")throw new Error("Invalid options parameter. It requires an object.");if(r.hash===void 0||typeof r.hash!="string")throw new Error("Hash should be specified")})(A);let t=((r,C,o)=>{let h=C.match(/^\$argon2(id|i|d)\$v=([0-9]+)\$((?:[mtp]=[0-9]+,){2}[mtp]=[0-9]+)\$([A-Za-z0-9+/]+)\$([A-Za-z0-9+/]+)$/);if(!h)throw new Error("Invalid hash");let[,a,Q,w,D,c]=h;if(Q!=="19")throw new Error(`Unsupported version: ${Q}`);let k={},n={m:"memorySize",p:"parallelism",t:"iterations"};for(let s of w.split(",")){let[f,p]=s.split("=");k[n[f]]=Number(p)}return Object.assign(Object.assign({},k),{password:r,secret:o,hashType:a,salt:nA(D),hashLength:CA(c),outputType:"encoded"})})(A.password,A.hash,A.secret);M(t);let e=A.hash.lastIndexOf("$")+1;return(yield O(t)).substring(e)===A.hash.substring(e)}))},I.argon2d=function(A){return i(this,void 0,void 0,(function*(){return M(A),O(Object.assign(Object.assign({},A),{hashType:"d"}))}))},I.argon2i=function(A){return i(this,void 0,void 0,(function*(){return M(A),O(Object.assign(Object.assign({},A),{hashType:"i"}))}))},I.argon2id=function(A){return i(this,void 0,void 0,(function*(){return M(A),O(Object.assign(Object.assign({},A),{hashType:"id"}))}))}}))});var _A={};GA(_A,{VaultPasswordError:()=>N,createArgon2idMetadata:()=>z,createKeyTransferReceiver:()=>TA,createPasswordWrappedRemoteVaultKey:()=>bA,decodeBase64:()=>F,decryptTransferredVaultKey:()=>qA,deriveWrapKey:()=>R,encodeBase64:()=>d,encryptVaultKeyForReceiver:()=>ZA,keyTransferVerificationCode:()=>WA,randomBytes:()=>H,toArrayBuffer:()=>y,unwrapRemoteVaultKeyWithPassword:()=>YA,validateKeyTransferPublicKey:()=>LA,validateVaultPassword:()=>xA,wrapRemoteVaultKeyWithPassword:()=>cA});function H(I){return crypto.getRandomValues(new Uint8Array(I))}function d(I){let i=[];for(let g=0;gKA(sA(),1)),B=g.default?.argon2id??g["module.exports"]?.argon2id;if(!B)throw new Error("argon2id module failed to load");let E=await B({password:new TextEncoder().encode(I),salt:F(i.salt),iterations:i.iterations,parallelism:i.parallelism,memorySize:i.memoryKiB,hashLength:JA,outputType:"binary"});return await crypto.subtle.importKey("raw",y(E),{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}var wA="aes-256-gcm",fA=1,$=1,EA=32,HA=12,N=class extends Error{constructor(g,B){super(B);this.code=g;this.name="VaultPasswordError"}};async function bA(I,i={}){let g=H(EA);return{remoteVaultKey:g,envelope:await cA(I,g,i)}}async function cA(I,i,g={}){if(i.byteLength!==EA)throw new Error("Invalid vault key length");let B=z(g.kdfOverrides),E=await R(DA(I),B),U=H(HA),K=await NA(E,i,U,g.binding);return{version:g.binding?2:fA,keyVersion:$,...g.binding?{binding:g.binding}:{},kdf:B,wrap:{algorithm:wA,nonce:d(U),ciphertext:d(K)}}}async function YA(I,i,g){let B=DA(I);if(PA(i),i.version===2&&(!g||!i.binding||i.binding.vaultId!==g.vaultId||i.binding.userId!==g.userId))throw new Error("Vault password wrapper belongs to a different vault or user");let E=F(i.kdf.salt),U=F(i.wrap.nonce),K=F(i.wrap.ciphertext),T=await R(B,{...i.kdf,salt:d(E)}),P=await crypto.subtle.decrypt({name:"AES-GCM",iv:y(U),...i.version===2?{additionalData:pA(i.binding)}:{}},T,y(K));return new Uint8Array(P)}async function NA(I,i,g,B){let E=await crypto.subtle.encrypt({name:"AES-GCM",iv:y(g),...B?{additionalData:pA(B)}:{}},I,y(i));return new Uint8Array(E)}function PA(I){if(I.version!==fA&&I.version!==2)throw new Error(`unsupported wrapper version: ${I.version}`);if(I.keyVersion!==$||I.version===1&&I.binding||I.version===2&&(!I.binding?.userId||!I.binding.vaultId))throw new Error("Invalid password wrapper binding or key version");if(I.wrap.algorithm!==wA)throw new Error(`unsupported wrap algorithm: ${I.wrap.algorithm}`)}function DA(I){if(!I)throw new N("required","Password is required.");if(I!==I.trim())throw new N("outer_spaces","Password cannot start or end with spaces.");return I}function pA(I){return new Uint8Array(new TextEncoder().encode(JSON.stringify(["synch.password-wrapper",2,I.vaultId,I.userId,$])))}var OA=new Set(["123456","123456789","1234567890","password","password1","password123","qwerty","qwerty123","letmein","admin","welcome","iloveyou","vault","vaultpassword","synch","synchpassword","obsidian","obsidianvault","obsidianvaultpassword","synchvaultpassword"]),MA=["password","qwerty","letmein","admin","welcome","iloveyou","vault","synch","obsidian"];function xA(I){return I?I!==I.trim()?{ok:!1,code:"outer_spaces",message:"Password cannot start or end with spaces."}:I.length<12?{ok:!1,code:"min_length",count:12,message:"Password must be at least 12 characters."}:I.length>256?{ok:!1,code:"max_length",count:256,message:"Password must be 256 characters or fewer."}:XA(I)?{ok:!1,code:"too_weak",message:"Password is too easy to guess. Use a longer passphrase."}:vA(I)?{ok:!1,code:"repeated_character",message:"Password cannot be one repeated character."}:RA(I)?{ok:!1,code:"simple_sequence",message:"Password cannot be a simple sequence."}:{ok:!0}:{ok:!1,code:"required",message:"Password is required."}}function vA(I){return new Set(I.toLowerCase()).size===1}function XA(I){let i=I.toLowerCase().replace(/[^a-z0-9]/g,"");if(OA.has(i))return!0;for(let g of MA)i=i.split(g).join("");return i===""||/^[0-9]+$/.test(i)}function RA(I){if(!/^[a-z]+$/i.test(I)&&!/^[0-9]+$/.test(I))return!1;let i=I.toLowerCase(),g=i.charCodeAt(1)-i.charCodeAt(0);if(g!==1&&g!==-1)return!1;for(let B=1;BK.toString(16).padStart(2,"0")).join("").match(/.{4}/g).join("-")}async function ZA(I,i,g){if(I.byteLength!==32)throw new Error("Invalid vault key length");let B=await crypto.subtle.encrypt({name:"RSA-OAEP",label:iA(g)},await IA(i),y(I));return{version:1,algorithm:"rsa-oaep-sha256",ciphertext:d(new Uint8Array(B))}}async function qA(I,i,g){if(I.version!==1||I.algorithm!=="rsa-oaep-sha256"||F(I.ciphertext).length!==384)throw new Error("Invalid key transfer envelope");let B=await crypto.subtle.importKey("pkcs8",y(F(i)),AA,!1,["decrypt"]),E=new Uint8Array(await crypto.subtle.decrypt({name:"RSA-OAEP",label:iA(g)},B,y(F(I.ciphertext))));if(E.byteLength!==32)throw new Error("Invalid transferred key length");return E}return mA(_A);})(); /*! Bundled license information: hash-wasm/dist/argon2.umd.min.js: diff --git a/apps/api/public/vaults.html b/apps/api/public/vaults.html index 882d44e1..4653fd70 100644 --- a/apps/api/public/vaults.html +++ b/apps/api/public/vaults.html @@ -7,6 +7,7 @@ +
@@ -28,6 +29,7 @@

Remote vaults

+
Loading vaults...
@@ -64,7 +66,7 @@

Create remote vault

-

The password cannot be recovered, so store it somewhere safe. You will enter the same password when connecting this vault from Obsidian.

+

Keep this password safe. If it is lost, recovery requires another vault administrator who still has the vault key.

+