Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion vendor-sphere-sdk/SHA.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1499a93
96991eb
8 changes: 8 additions & 0 deletions vendor-sphere-sdk/dist/core/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -60296,6 +60296,14 @@ var Sphere = class _Sphere {
fallbackThrew = err;
}
if (fallbackValue !== null && fallbackValue !== void 0) {
try {
await this._storage.set(key, fallbackValue);
} catch (err) {
logger.debug(
"Sphere",
`Identity backfill of "${key}" into primary storage failed; the next boot will re-consult fallback. (${err instanceof Error ? err.message : String(err)})`
);
}
return fallbackValue;
}
if (primaryThrew !== null) {
Expand Down
2 changes: 1 addition & 1 deletion vendor-sphere-sdk/dist/core/index.cjs.map

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions vendor-sphere-sdk/dist/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60205,6 +60205,14 @@ var Sphere = class _Sphere {
fallbackThrew = err;
}
if (fallbackValue !== null && fallbackValue !== void 0) {
try {
await this._storage.set(key, fallbackValue);
} catch (err) {
logger.debug(
"Sphere",
`Identity backfill of "${key}" into primary storage failed; the next boot will re-consult fallback. (${err instanceof Error ? err.message : String(err)})`
);
}
return fallbackValue;
}
if (primaryThrew !== null) {
Expand Down
2 changes: 1 addition & 1 deletion vendor-sphere-sdk/dist/core/index.js.map

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions vendor-sphere-sdk/dist/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -60657,6 +60657,14 @@ var Sphere = class _Sphere {
fallbackThrew = err;
}
if (fallbackValue !== null && fallbackValue !== void 0) {
try {
await this._storage.set(key, fallbackValue);
} catch (err) {
logger.debug(
"Sphere",
`Identity backfill of "${key}" into primary storage failed; the next boot will re-consult fallback. (${err instanceof Error ? err.message : String(err)})`
);
}
return fallbackValue;
}
if (primaryThrew !== null) {
Expand Down
2 changes: 1 addition & 1 deletion vendor-sphere-sdk/dist/index.cjs.map

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions vendor-sphere-sdk/dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60460,6 +60460,14 @@ var Sphere = class _Sphere {
fallbackThrew = err;
}
if (fallbackValue !== null && fallbackValue !== void 0) {
try {
await this._storage.set(key, fallbackValue);
} catch (err) {
logger.debug(
"Sphere",
`Identity backfill of "${key}" into primary storage failed; the next boot will re-consult fallback. (${err instanceof Error ? err.message : String(err)})`
);
}
return fallbackValue;
}
if (primaryThrew !== null) {
Expand Down
2 changes: 1 addition & 1 deletion vendor-sphere-sdk/dist/index.js.map

Large diffs are not rendered by default.

23 changes: 22 additions & 1 deletion vendor-sphere-sdk/dist/profile/browser.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -13253,10 +13253,25 @@ var PROFILE_KEY_MAPPING = {
"sent": { profileKey: "{addr}.sent", dynamic: true }
};
var CACHE_ONLY_KEYS = /* @__PURE__ */ new Set([
// External-API caches (regenerated from network)
"token_registry_cache",
"token_registry_cache_ts",
"price_cache",
"price_cache_ts"
"price_cache_ts",
// Identity / seed material — NEVER replicate via OrbitDB/IPFS.
// Keep this list in sync with IDENTITY_KEYS below.
"mnemonic",
"master_key",
"chain_code",
"derivation_path",
"base_path",
"derivation_mode",
"wallet_source",
// `current_address_index` is the active HD slot pointer. Could be cross-
// device synced in principle, but on a fresh-device boot the address-
// discovery walker re-derives it from the mnemonic anyway; keeping it
// device-local removes one more identity-shaped key from the OpLog.
"current_address_index"
]);
var IPFS_STATE_KEYS_PATTERN = /^ipfs_(seq|cid|ver)_/;
function computeAddressId(directAddress) {
Expand Down Expand Up @@ -21782,6 +21797,12 @@ var ProfileStorageProvider = class _ProfileStorageProvider {
if (translated.excluded) {
return;
}
if (translated.profileKey.startsWith("identity.") && !translated.cacheOnly) {
throw new ProfileError(
"PROFILE_NOT_INITIALIZED",
`Refusing to write identity-shaped Profile key "${translated.profileKey}" to OrbitDB: seed material must NEVER replicate. Add the legacy key "${key}" to CACHE_ONLY_KEYS in profile/types.ts. See IDENTITY_KEYS for the canonical list.`
);
}
await this.localCache.set(key, value);
if (translated.cacheOnly) {
return;
Expand Down
2 changes: 1 addition & 1 deletion vendor-sphere-sdk/dist/profile/browser.cjs.map

Large diffs are not rendered by default.

23 changes: 22 additions & 1 deletion vendor-sphere-sdk/dist/profile/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -13218,10 +13218,25 @@ var PROFILE_KEY_MAPPING = {
"sent": { profileKey: "{addr}.sent", dynamic: true }
};
var CACHE_ONLY_KEYS = /* @__PURE__ */ new Set([
// External-API caches (regenerated from network)
"token_registry_cache",
"token_registry_cache_ts",
"price_cache",
"price_cache_ts"
"price_cache_ts",
// Identity / seed material — NEVER replicate via OrbitDB/IPFS.
// Keep this list in sync with IDENTITY_KEYS below.
"mnemonic",
"master_key",
"chain_code",
"derivation_path",
"base_path",
"derivation_mode",
"wallet_source",
// `current_address_index` is the active HD slot pointer. Could be cross-
// device synced in principle, but on a fresh-device boot the address-
// discovery walker re-derives it from the mnemonic anyway; keeping it
// device-local removes one more identity-shaped key from the OpLog.
"current_address_index"
]);
var IPFS_STATE_KEYS_PATTERN = /^ipfs_(seq|cid|ver)_/;
function computeAddressId(directAddress) {
Expand Down Expand Up @@ -21749,6 +21764,12 @@ var ProfileStorageProvider = class _ProfileStorageProvider {
if (translated.excluded) {
return;
}
if (translated.profileKey.startsWith("identity.") && !translated.cacheOnly) {
throw new ProfileError(
"PROFILE_NOT_INITIALIZED",
`Refusing to write identity-shaped Profile key "${translated.profileKey}" to OrbitDB: seed material must NEVER replicate. Add the legacy key "${key}" to CACHE_ONLY_KEYS in profile/types.ts. See IDENTITY_KEYS for the canonical list.`
);
}
await this.localCache.set(key, value);
if (translated.cacheOnly) {
return;
Expand Down
2 changes: 1 addition & 1 deletion vendor-sphere-sdk/dist/profile/browser.js.map

Large diffs are not rendered by default.

59 changes: 56 additions & 3 deletions vendor-sphere-sdk/dist/profile/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -11523,6 +11523,7 @@ __export(profile_exports, {
DEFAULT_ENCRYPTION_CONFIG: () => DEFAULT_ENCRYPTION_CONFIG,
DEFAULT_LIST_KEYS_MAX_RESULTS: () => DEFAULT_LIST_KEYS_MAX_RESULTS,
DispositionWriter: () => DispositionWriter,
IDENTITY_KEYS: () => IDENTITY_KEYS,
IPFS_STATE_KEYS_PATTERN: () => IPFS_STATE_KEYS_PATTERN,
InMemoryDispositionStorageAdapter: () => InMemoryDispositionStorageAdapter,
Lamport: () => Lamport,
Expand Down Expand Up @@ -11668,10 +11669,35 @@ var PROFILE_KEY_MAPPING = {
"sent": { profileKey: "{addr}.sent", dynamic: true }
};
var CACHE_ONLY_KEYS = /* @__PURE__ */ new Set([
// External-API caches (regenerated from network)
"token_registry_cache",
"token_registry_cache_ts",
"price_cache",
"price_cache_ts"
"price_cache_ts",
// Identity / seed material — NEVER replicate via OrbitDB/IPFS.
// Keep this list in sync with IDENTITY_KEYS below.
"mnemonic",
"master_key",
"chain_code",
"derivation_path",
"base_path",
"derivation_mode",
"wallet_source",
// `current_address_index` is the active HD slot pointer. Could be cross-
// device synced in principle, but on a fresh-device boot the address-
// discovery walker re-derives it from the mnemonic anyway; keeping it
// device-local removes one more identity-shaped key from the OpLog.
"current_address_index"
]);
var IDENTITY_KEYS = /* @__PURE__ */ new Set([
"mnemonic",
"master_key",
"chain_code",
"derivation_path",
"base_path",
"derivation_mode",
"wallet_source",
"current_address_index"
]);
var IPFS_STATE_KEYS_PATTERN = /^ipfs_(seq|cid|ver)_/;
function computeAddressId(directAddress) {
Expand Down Expand Up @@ -22325,6 +22351,12 @@ var ProfileStorageProvider = class _ProfileStorageProvider {
if (translated.excluded) {
return;
}
if (translated.profileKey.startsWith("identity.") && !translated.cacheOnly) {
throw new ProfileError(
"PROFILE_NOT_INITIALIZED",
`Refusing to write identity-shaped Profile key "${translated.profileKey}" to OrbitDB: seed material must NEVER replicate. Add the legacy key "${key}" to CACHE_ONLY_KEYS in profile/types.ts. See IDENTITY_KEYS for the canonical list.`
);
}
await this.localCache.set(key, value);
if (translated.cacheOnly) {
return;
Expand Down Expand Up @@ -28860,7 +28892,7 @@ var ProfileMigration = class _ProfileMigration {
await this.setPhase(legacyStorage, "complete");
const result = {
success: true,
keysMigrated: transformed.profileKeys.size,
keysMigrated: transformed.profileKeys.size + transformed.identityKeys.size,
tokensMigrated: transformed.tokenIds.size,
addressesMigrated: countAddresses(transformed),
durationMs: Date.now() - startTime
Expand All @@ -28873,7 +28905,7 @@ var ProfileMigration = class _ProfileMigration {
this.log("Migration failed at phase", currentPhase, ":", errorMsg);
return {
success: false,
keysMigrated: transformed?.profileKeys.size ?? 0,
keysMigrated: (transformed?.profileKeys.size ?? 0) + (transformed?.identityKeys.size ?? 0),
tokensMigrated: transformed?.tokenIds.size ?? 0,
addressesMigrated: transformed !== null ? countAddresses(transformed) : 0,
durationMs: Date.now() - startTime,
Expand Down Expand Up @@ -28942,6 +28974,7 @@ var ProfileMigration = class _ProfileMigration {
async stepTransformLocal(legacyStorage, legacyTokenStorage) {
this.log("Step 2: TRANSFORM LOCAL");
const profileKeys = /* @__PURE__ */ new Map();
const identityKeys = /* @__PURE__ */ new Map();
const tokenIds = /* @__PURE__ */ new Set();
let historyCount = 0;
let conversationCount = 0;
Expand All @@ -28962,6 +28995,10 @@ var ProfileMigration = class _ProfileMigration {
}
const value = await legacyStorage.get(rawKey);
if (value === null) continue;
if (IDENTITY_KEYS.has(stripped)) {
identityKeys.set(stripped, value);
continue;
}
const profileKey = mapLegacyKeyToProfileKey(stripped);
if (profileKey === null) continue;
profileKeys.set(profileKey, value);
Expand Down Expand Up @@ -29021,6 +29058,7 @@ var ProfileMigration = class _ProfileMigration {
}
return {
profileKeys,
identityKeys,
txfData,
tokenIds,
historyCount,
Expand Down Expand Up @@ -29058,6 +29096,21 @@ var ProfileMigration = class _ProfileMigration {
}
}
this.log(`Wrote ${keysWritten} profile keys`);
let identityKeysWritten = 0;
for (const [legacyKey, value] of data.identityKeys) {
try {
await storage.set(legacyKey, value);
identityKeysWritten++;
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
throw new ProfileError(
"MIGRATION_FAILED",
`Failed to write identity key '${legacyKey}': ${msg}`,
err
);
}
}
this.log(`Wrote ${identityKeysWritten} identity keys (cache-only, never OrbitDB)`);
if (data.txfData !== null) {
const saveResult = await profileTokenStorage.save(data.txfData);
if (!saveResult.success) {
Expand Down
2 changes: 1 addition & 1 deletion vendor-sphere-sdk/dist/profile/index.cjs.map

Large diffs are not rendered by default.

33 changes: 31 additions & 2 deletions vendor-sphere-sdk/dist/profile/index.d.cts
Original file line number Diff line number Diff line change
Expand Up @@ -22438,11 +22438,40 @@ type ProfileKeyMap = Readonly<Record<string, ProfileKeyMapEntry>>;
declare const PROFILE_KEY_MAPPING: ProfileKeyMap;
/**
* Keys that are stored ONLY in the local cache, never written to OrbitDB.
* These are regenerated from external APIs and are not replicated.
*
* Two distinct reasons land a key here:
*
* 1. **External-API caches** (`token_registry_*`, `price_*`) — regenerated
* from network calls; replicating wastes OpLog bytes and stale entries
* on one device can poison a cross-device read.
*
* 2. **Identity / seed material** (the IDENTITY_KEYS block) —
* *security boundary*. OrbitDB content is replicated to IPFS (the
* snapshot CAR is pinned by the user's own pin gateway *and*, in
* practice, observable by any peer the pubsub topic reaches). Even
* when wrapped by the password-derived `encrypt()`, distributing the
* encrypted seed lowers the threat model from "attacker must
* compromise the device" to "attacker must brute-force a password
* against an IPFS-pinned ciphertext". The seed MUST stay
* device-local; the only legitimate cross-device transport for the
* seed is the user's own BIP-39 mnemonic backup. Audit #333 C1 was
* interpreted as "encrypt before OrbitDB write" — that defense holds
* only during Phase A (no key derived → `encrypt()` throws); any
* post-Phase-A rewrite of an identity key would otherwise succeed
* encrypted and leak. Mark them cache-only so the write short-
* circuits at the localCache step in `ProfileStorageProvider.set()`.
*
* See PROFILE-ARCHITECTURE.md Section 2.1 "Cache-only keys".
*/
declare const CACHE_ONLY_KEYS: ReadonlySet<string>;
/**
* The identity / seed-material keys. Listed separately so other modules
* (migration, audits, tests) can refer to "the identity class" without
* coupling to the full CACHE_ONLY_KEYS list.
*
* Every key here MUST also appear in CACHE_ONLY_KEYS.
*/
declare const IDENTITY_KEYS: ReadonlySet<string>;
/**
* Regex pattern matching IPFS/IPNS state keys that are obsoleted by OrbitDB.
* These keys are consumed during migration but NOT carried forward to the Profile.
Expand Down Expand Up @@ -29660,4 +29689,4 @@ interface NodeProfileProvidersFromSphereConfig {
readonly oracle?: OracleProvider;
}

export { type BrowserProfileProviders, type BrowserProfileProvidersConfig, type BrowserProfileProvidersFromSphereConfig, CACHE_ONLY_KEYS, CAS_MAX_RETRIES, CID_REF_SCHEMA_VERSION, type CidRef, CidRefStore, type CidRefStoreOptions, ConsolidationEngine, type ConsolidationPendingState, type ConsolidationResult, DEFAULT_ENCRYPTION_CONFIG, DEFAULT_LIST_KEYS_MAX_RESULTS, type DispositionEventEmitter, type DispositionPerEntryStorage, DispositionWriter, type DispositionWriterOptions, type FetchOptions, IPFS_STATE_KEYS_PATTERN, InMemoryDispositionStorageAdapter, Lamport, type LegacyImportOptions, type LegacyImportResult, MAX_LOCK_HOLD_MS, ManifestCas, ManifestCasConcurrentModificationError, type ManifestCasResult, ManifestStore, type ManifestStoreOptions, type MigrateLegacyToProfileFromSphereOptions, type MigrateLegacyToProfileFromSphereResult, type MigrateLegacyToProfileOptions, type MigrationDirection, type MigrationPhase, type MigrationResult, type MinimalManifestStorage, type NodeProfileProviders, type NodeProfileProvidersConfig, type NodeProfileProvidersFromSphereConfig, NostrReplicationBridge, type NostrReplicationConfig, OrbitDbAdapter, type OrbitDbConfig, OrbitDbDispositionStorageAdapter, type OrbitDbDispositionStorageAdapterOptions, PROFILE_CACHE_PURPOSE, PROFILE_HKDF_INFO, PROFILE_KEY_MAPPING, PerTokenMutex, type PerTokenMutexOptions, type PerTokenMutexStrategy, type PinOptions, type ProfileConfig, type ProfileDatabase, type ProfileEncryptionConfig, ProfileError, type ProfileErrorCode, type ProfileKeyMap, type ProfileKeyMapEntry, ProfileMigration, type ProfileProviders, ProfileStorageProvider, type ProfileStorageProviderOptions, ProfileTokenStorageProvider, type ProfileTokenStorageProviderOptions, type SphereCryptographer, type SphereCryptographerPurpose, type SyncEventCallback, type SyncEventType, TOKEN_STORAGE_MIGRATION_MARKER_VERSION, type TokenManifest, type TokenManifestEntry, type TokenManifestStatus, type TokenStorageMigrationCounts, type TokenStorageMigrationOptions, type TokenStorageMigrationProgress, type TokenStorageMigrationResult, type UxfBundleRef, auditKeyFor, clearTokenStorageMigrationMarker, computeAddressId, conflictingTokenIds, createProfileProviders, decryptProfileValue, decryptString, deriveHistoryFromArchived, deriveProfileEncryptionKey, deriveSentFromArchived, deriveStructuralManifest, deriveTombstonesFromArchived, encryptProfileValue, encryptString, fetchCarFromIpfs, fetchFromIpfs, importLegacyTokens, invalidKeyFor, isConflictingStatus, isTokenStorageMigrationComplete, mergeAuditEntry, mergeManifestEntry, migrateLegacyToProfile, migrateProfileToLegacy, migrateTokenStorage, pinCarBlocksToIpfs, pinToIpfs, verifyCidAccessible };
export { type BrowserProfileProviders, type BrowserProfileProvidersConfig, type BrowserProfileProvidersFromSphereConfig, CACHE_ONLY_KEYS, CAS_MAX_RETRIES, CID_REF_SCHEMA_VERSION, type CidRef, CidRefStore, type CidRefStoreOptions, ConsolidationEngine, type ConsolidationPendingState, type ConsolidationResult, DEFAULT_ENCRYPTION_CONFIG, DEFAULT_LIST_KEYS_MAX_RESULTS, type DispositionEventEmitter, type DispositionPerEntryStorage, DispositionWriter, type DispositionWriterOptions, type FetchOptions, IDENTITY_KEYS, IPFS_STATE_KEYS_PATTERN, InMemoryDispositionStorageAdapter, Lamport, type LegacyImportOptions, type LegacyImportResult, MAX_LOCK_HOLD_MS, ManifestCas, ManifestCasConcurrentModificationError, type ManifestCasResult, ManifestStore, type ManifestStoreOptions, type MigrateLegacyToProfileFromSphereOptions, type MigrateLegacyToProfileFromSphereResult, type MigrateLegacyToProfileOptions, type MigrationDirection, type MigrationPhase, type MigrationResult, type MinimalManifestStorage, type NodeProfileProviders, type NodeProfileProvidersConfig, type NodeProfileProvidersFromSphereConfig, NostrReplicationBridge, type NostrReplicationConfig, OrbitDbAdapter, type OrbitDbConfig, OrbitDbDispositionStorageAdapter, type OrbitDbDispositionStorageAdapterOptions, PROFILE_CACHE_PURPOSE, PROFILE_HKDF_INFO, PROFILE_KEY_MAPPING, PerTokenMutex, type PerTokenMutexOptions, type PerTokenMutexStrategy, type PinOptions, type ProfileConfig, type ProfileDatabase, type ProfileEncryptionConfig, ProfileError, type ProfileErrorCode, type ProfileKeyMap, type ProfileKeyMapEntry, ProfileMigration, type ProfileProviders, ProfileStorageProvider, type ProfileStorageProviderOptions, ProfileTokenStorageProvider, type ProfileTokenStorageProviderOptions, type SphereCryptographer, type SphereCryptographerPurpose, type SyncEventCallback, type SyncEventType, TOKEN_STORAGE_MIGRATION_MARKER_VERSION, type TokenManifest, type TokenManifestEntry, type TokenManifestStatus, type TokenStorageMigrationCounts, type TokenStorageMigrationOptions, type TokenStorageMigrationProgress, type TokenStorageMigrationResult, type UxfBundleRef, auditKeyFor, clearTokenStorageMigrationMarker, computeAddressId, conflictingTokenIds, createProfileProviders, decryptProfileValue, decryptString, deriveHistoryFromArchived, deriveProfileEncryptionKey, deriveSentFromArchived, deriveStructuralManifest, deriveTombstonesFromArchived, encryptProfileValue, encryptString, fetchCarFromIpfs, fetchFromIpfs, importLegacyTokens, invalidKeyFor, isConflictingStatus, isTokenStorageMigrationComplete, mergeAuditEntry, mergeManifestEntry, migrateLegacyToProfile, migrateProfileToLegacy, migrateTokenStorage, pinCarBlocksToIpfs, pinToIpfs, verifyCidAccessible };
Loading
Loading