@oxyhq/core 4.0.1 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/dist/cjs/.tsbuildinfo +1 -1
  2. package/dist/cjs/HttpService.js +6 -18
  3. package/dist/cjs/OxyServices.base.js +0 -21
  4. package/dist/cjs/crypto/keyManager.js +7 -7
  5. package/dist/cjs/crypto/polyfill.js +6 -5
  6. package/dist/cjs/crypto/signatureService.js +44 -220
  7. package/dist/cjs/index.js +4 -8
  8. package/dist/cjs/mixins/OxyServices.accounts.js +90 -0
  9. package/dist/cjs/mixins/OxyServices.assets.js +68 -2
  10. package/dist/cjs/mixins/OxyServices.auth.js +3 -3
  11. package/dist/cjs/mixins/OxyServices.civic.js +3 -3
  12. package/dist/cjs/mixins/OxyServices.language.js +2 -2
  13. package/dist/cjs/mixins/OxyServices.utility.js +7 -95
  14. package/dist/cjs/utils/cacheKey.js +17 -19
  15. package/dist/cjs/utils/deviceManager.js +2 -2
  16. package/dist/cjs/utils/platform.js +0 -14
  17. package/dist/esm/.tsbuildinfo +1 -1
  18. package/dist/esm/HttpService.js +6 -18
  19. package/dist/esm/OxyServices.base.js +0 -21
  20. package/dist/esm/crypto/keyManager.js +4 -4
  21. package/dist/esm/crypto/polyfill.js +5 -4
  22. package/dist/esm/crypto/signatureService.js +39 -214
  23. package/dist/esm/index.js +1 -2
  24. package/dist/esm/mixins/OxyServices.accounts.js +90 -0
  25. package/dist/esm/mixins/OxyServices.assets.js +67 -1
  26. package/dist/esm/mixins/OxyServices.auth.js +1 -1
  27. package/dist/esm/mixins/OxyServices.civic.js +3 -3
  28. package/dist/esm/mixins/OxyServices.language.js +1 -1
  29. package/dist/esm/mixins/OxyServices.utility.js +6 -94
  30. package/dist/esm/utils/cacheKey.js +17 -19
  31. package/dist/esm/utils/deviceManager.js +1 -1
  32. package/dist/esm/utils/platform.js +0 -12
  33. package/dist/types/.tsbuildinfo +1 -1
  34. package/dist/types/HttpService.d.ts +3 -6
  35. package/dist/types/OxyServices.base.d.ts +0 -17
  36. package/dist/types/crypto/polyfill.d.ts +2 -2
  37. package/dist/types/crypto/signatureService.d.ts +18 -84
  38. package/dist/types/index.d.ts +4 -5
  39. package/dist/types/mixins/OxyServices.accounts.d.ts +66 -5
  40. package/dist/types/mixins/OxyServices.analytics.d.ts +0 -2
  41. package/dist/types/mixins/OxyServices.appData.d.ts +0 -2
  42. package/dist/types/mixins/OxyServices.assets.d.ts +42 -3
  43. package/dist/types/mixins/OxyServices.auth.d.ts +0 -2
  44. package/dist/types/mixins/OxyServices.civic.d.ts +3 -5
  45. package/dist/types/mixins/OxyServices.connectedApps.d.ts +0 -2
  46. package/dist/types/mixins/OxyServices.contacts.d.ts +0 -2
  47. package/dist/types/mixins/OxyServices.devices.d.ts +0 -2
  48. package/dist/types/mixins/OxyServices.features.d.ts +0 -2
  49. package/dist/types/mixins/OxyServices.fedcm.d.ts +0 -2
  50. package/dist/types/mixins/OxyServices.identity.d.ts +8 -5
  51. package/dist/types/mixins/OxyServices.language.d.ts +0 -2
  52. package/dist/types/mixins/OxyServices.links.d.ts +0 -2
  53. package/dist/types/mixins/OxyServices.location.d.ts +0 -2
  54. package/dist/types/mixins/OxyServices.nodes.d.ts +0 -44
  55. package/dist/types/mixins/OxyServices.payment.d.ts +0 -2
  56. package/dist/types/mixins/OxyServices.privacy.d.ts +0 -2
  57. package/dist/types/mixins/OxyServices.redirect.d.ts +0 -2
  58. package/dist/types/mixins/OxyServices.reputation.d.ts +0 -2
  59. package/dist/types/mixins/OxyServices.security.d.ts +0 -2
  60. package/dist/types/mixins/OxyServices.silent.d.ts +0 -2
  61. package/dist/types/mixins/OxyServices.sso.d.ts +0 -2
  62. package/dist/types/mixins/OxyServices.topics.d.ts +0 -2
  63. package/dist/types/mixins/OxyServices.user.d.ts +0 -2
  64. package/dist/types/mixins/OxyServices.utility.d.ts +0 -32
  65. package/dist/types/models/interfaces.d.ts +18 -0
  66. package/dist/types/server/auth.d.ts +0 -6
  67. package/dist/types/server/index.d.ts +1 -1
  68. package/dist/types/utils/cacheKey.d.ts +6 -7
  69. package/dist/types/utils/platform.d.ts +0 -8
  70. package/package.json +4 -7
  71. package/src/HttpService.ts +6 -22
  72. package/src/OxyServices.base.ts +0 -23
  73. package/src/__tests__/httpServiceCache.test.ts +0 -19
  74. package/src/crypto/__tests__/keyManager.atomicity.test.ts +2 -1
  75. package/src/crypto/__tests__/keyManager.test.ts +9 -7
  76. package/src/crypto/__tests__/signChallengeShared.test.ts +2 -1
  77. package/src/crypto/__tests__/signedRecord.test.ts +37 -150
  78. package/src/crypto/keyManager.ts +28 -17
  79. package/src/crypto/polyfill.ts +5 -4
  80. package/src/crypto/signatureService.ts +67 -255
  81. package/src/index.ts +4 -3
  82. package/src/mixins/OxyServices.accounts.ts +136 -3
  83. package/src/mixins/OxyServices.assets.ts +96 -2
  84. package/src/mixins/OxyServices.auth.ts +1 -1
  85. package/src/mixins/OxyServices.civic.ts +6 -17
  86. package/src/mixins/OxyServices.identity.ts +8 -2
  87. package/src/mixins/OxyServices.language.ts +1 -1
  88. package/src/mixins/OxyServices.nodes.ts +1 -12
  89. package/src/mixins/OxyServices.utility.ts +6 -119
  90. package/src/mixins/__tests__/OxyServices.civic.test.ts +2 -2
  91. package/src/mixins/__tests__/OxyServices.serviceAssetMetadata.test.ts +116 -0
  92. package/src/mixins/__tests__/accounts.test.ts +120 -0
  93. package/src/models/interfaces.ts +19 -0
  94. package/src/server/auth.ts +0 -7
  95. package/src/server/index.ts +0 -1
  96. package/src/utils/__tests__/cacheKey.test.ts +0 -0
  97. package/src/utils/cacheKey.ts +16 -21
  98. package/src/utils/deviceManager.ts +1 -1
  99. package/src/utils/platform.ts +0 -14
  100. package/dist/cjs/crypto/canonicalJson.js +0 -107
  101. package/dist/cjs/utils/platformCrypto.js +0 -165
  102. package/dist/cjs/utils/platformCrypto.native.js +0 -123
  103. package/dist/esm/crypto/canonicalJson.js +0 -104
  104. package/dist/esm/utils/platformCrypto.js +0 -125
  105. package/dist/esm/utils/platformCrypto.native.js +0 -80
  106. package/dist/types/crypto/canonicalJson.d.ts +0 -44
  107. package/dist/types/utils/platformCrypto.d.ts +0 -87
  108. package/dist/types/utils/platformCrypto.native.d.ts +0 -54
  109. package/src/crypto/__tests__/canonicalJson.test.ts +0 -116
  110. package/src/crypto/canonicalJson.ts +0 -120
  111. package/src/utils/platformCrypto.native.ts +0 -101
  112. package/src/utils/platformCrypto.ts +0 -145
@@ -79,7 +79,6 @@ export declare class HttpService {
79
79
  * Each listener receives the resulting access token, or `null` when cleared.
80
80
  */
81
81
  private _tokenChangeListeners;
82
- private _actingAsUserId;
83
82
  private requestMetrics;
84
83
  constructor(config: OxyConfig);
85
84
  private syncAccessTokenFromProvider;
@@ -153,9 +152,9 @@ export declare class HttpService {
153
152
  * Derive a stable, non-sensitive identity discriminator for cache scoping.
154
153
  *
155
154
  * Thin instance wrapper over the pure {@link computeIdentityTag} helper —
156
- * binds it to this instance's live access token and acting-as id. See that
157
- * function's docs for the full resolution contract (anon fallback, decoded
158
- * `userId || id`, token-hash fallback for undecodable tokens).
155
+ * binds it to this instance's live access token. See that function's docs for
156
+ * the full resolution contract (anon fallback, decoded `userId || id`,
157
+ * token-hash fallback for undecodable tokens).
159
158
  */
160
159
  private computeIdentityTag;
161
160
  /**
@@ -209,8 +208,6 @@ export declare class HttpService {
209
208
  put<T = unknown>(url: string, data?: unknown, config?: Omit<RequestConfig, 'method' | 'url' | 'data'>): Promise<T>;
210
209
  patch<T = unknown>(url: string, data?: unknown, config?: Omit<RequestConfig, 'method' | 'url' | 'data'>): Promise<T>;
211
210
  delete<T = unknown>(url: string, config?: Omit<RequestConfig, 'method' | 'url'>): Promise<T>;
212
- setActingAs(userId: string | null): void;
213
- getActingAs(): string | null;
214
211
  setTokens(accessToken: string): void;
215
212
  setAuthRefreshHandler(handler: AuthRefreshHandler | null): void;
216
213
  setAccessTokenProvider(provider: AccessTokenProvider | null): void;
@@ -153,23 +153,6 @@ export declare class OxyServicesBase {
153
153
  * the per-request preflight refresh; this powers the idle/background timer.
154
154
  */
155
155
  getAccessTokenExpiry(): number | null;
156
- /**
157
- * Set the acting-as identity for managed accounts.
158
- *
159
- * When set, all subsequent API requests will include the `X-Acting-As` header,
160
- * causing the server to attribute actions to the managed account. The
161
- * authenticated user must be an authorized manager of the target account.
162
- *
163
- * Pass `null` to clear and revert to the authenticated user's own identity.
164
- *
165
- * @param userId - The managed account user ID, or null to clear
166
- */
167
- setActingAs(userId: string | null): void;
168
- /**
169
- * Get the current acting-as identity (managed account user ID), or null
170
- * if operating as the authenticated user's own identity.
171
- */
172
- getActingAs(): string | null;
173
156
  /**
174
157
  * Wait for authentication to be ready
175
158
  *
@@ -6,8 +6,8 @@
6
6
  *
7
7
  * - Browser/Node.js: Uses native crypto
8
8
  * - React Native: Uses expo-crypto (statically imported via the
9
- * per-platform `platformCrypto` module — see that file's doc-comment for
10
- * how platform routing works).
9
+ * per-platform `platform/crypto` module in `@oxyhq/protocol` — see that
10
+ * file's doc-comment for how platform routing works).
11
11
  */
12
12
  import { Buffer } from 'buffer';
13
13
  export { Buffer };
@@ -1,51 +1,13 @@
1
1
  /**
2
- * Signature Service - ECDSA Digital Signatures
2
+ * Signature Service - ECDSA Digital Signatures (device-key bound)
3
3
  *
4
- * Handles signing and verification of messages using ECDSA secp256k1.
5
- * Used for authenticating requests and proving identity ownership.
4
+ * Handles signing and verification of messages with the user's DEVICE identity
5
+ * key (read from {@link KeyManager} / secure storage). All cryptography itself —
6
+ * canonical signing input, SHA-256, secp256k1 sign/verify, envelope assembly —
7
+ * is delegated to `@oxyhq/protocol`; this service only resolves the key from
8
+ * storage and orchestrates the protocol primitives.
6
9
  */
7
10
  import type { SignedRecordEnvelope } from '@oxyhq/contracts';
8
- /**
9
- * The signing-input portion of a {@link SignedRecordEnvelope}: every field
10
- * EXCEPT the `publicKey` and `signature`. Both the client (when signing) and
11
- * the server (when verifying) canonicalize exactly these fields, so they agree
12
- * on the bytes that the signature covers.
13
- *
14
- * The v2 chain fields (`seq`/`prev`/`collection`/`rkey`) are optional: a v1
15
- * envelope omits them and is signed over only the base fields; a v2 envelope
16
- * carries them and includes them in the signed bytes.
17
- */
18
- export type SignedRecordSigningFields = Pick<SignedRecordEnvelope, 'version' | 'type' | 'subject' | 'issuer' | 'record' | 'issuedAt'> & Partial<Pick<SignedRecordEnvelope, 'seq' | 'prev' | 'collection' | 'rkey'>>;
19
- /**
20
- * Compute the canonical signing input for a signed-record envelope.
21
- *
22
- * This is the single definition of "what the signature covers". `@oxyhq/core`
23
- * (client signing) and `@oxyhq/api` (server verification) both call this, so a
24
- * record signed by a client and verified by the server cannot drift.
25
- *
26
- * - **v1**: the canonical JSON of `{version, type, subject, issuer, record,
27
- * issuedAt}` — BYTE-IDENTICAL to the original scheme, so every signature
28
- * already in production keeps verifying.
29
- * - **v2**: the canonical JSON additionally includes the hash-chain fields
30
- * `{seq, prev, collection, rkey}`. Because {@link canonicalize} sorts keys,
31
- * the on-the-wire field order is irrelevant; the resulting canonical key
32
- * order is `collection, issuedAt, issuer, prev, record, rkey, seq, subject,
33
- * type, version`. `prev` is `null` at genesis (serialized as `null`, not
34
- * omitted), so it is always part of the signed bytes.
35
- */
36
- export declare function signedRecordSigningInput(fields: SignedRecordSigningFields): string;
37
- /**
38
- * Compute the `recordId` (content address) of a signed record: the SHA-256 hex
39
- * digest of its canonical {@link signedRecordSigningInput}.
40
- *
41
- * Deterministic and stable across runtimes (it reuses the same canonicalization
42
- * + SHA-256 the signature itself is built on). The recordId is what `prev`
43
- * references in the per-subject hash chain, so `@oxyhq/core` (client) and
44
- * `@oxyhq/api` (server) MUST compute it identically — both call this function.
45
- * It is taken over the SIGNING input (excluding `publicKey`/`signature`), so it
46
- * is a pure content address of the record's meaning, independent of who signed.
47
- */
48
- export declare function computeRecordId(fields: SignedRecordSigningFields): Promise<string>;
49
11
  export interface SignedMessage {
50
12
  message: string;
51
13
  signature: string;
@@ -68,29 +30,10 @@ export declare class SignatureService {
68
30
  */
69
31
  static hashMessage(message: string): Promise<string>;
70
32
  /**
71
- * Sign a message using the stored private key
33
+ * Sign a message using the stored device private key
72
34
  * Returns the signature in DER format (hex encoded)
73
35
  */
74
36
  static sign(message: string): Promise<string>;
75
- /**
76
- * Sign a message with an explicit private key (without storing)
77
- * Useful for one-time operations or testing
78
- */
79
- static signWithKey(message: string, privateKey: string): Promise<string>;
80
- /**
81
- * Verify a signature against a message and public key
82
- *
83
- * Returns false on any error (invalid signature, malformed input, etc.).
84
- * Errors are logged at debug level so they're available when troubleshooting
85
- * signature mismatches but don't surface to the caller.
86
- */
87
- static verify(message: string, signature: string, publicKey: string): Promise<boolean>;
88
- /**
89
- * Synchronous verification (for Node.js backend)
90
- * Uses crypto module directly for hashing
91
- * Note: This method should only be used in Node.js environments
92
- */
93
- static verifySync(message: string, signature: string, publicKey: string): boolean;
94
37
  /**
95
38
  * Create a signed message object with metadata
96
39
  */
@@ -113,9 +56,10 @@ export declare class SignatureService {
113
56
  * Mirrors {@link signChallenge} exactly — same message format
114
57
  * (`auth:${publicKey}:${challenge}:${timestamp}`) so the server verification
115
58
  * path is unchanged — but sources the shared public/private key from
116
- * `KeyManager` and signs with `signWithKey`. Used by "Sign in with Oxy"
117
- * same-device shared-keychain SSO (Mechanism A): a sibling native app proves
118
- * control of the shared identity to mint its own session.
59
+ * `KeyManager` and signs with the protocol's explicit-key {@link signMessage}.
60
+ * Used by "Sign in with Oxy" same-device shared-keychain SSO (Mechanism A): a
61
+ * sibling native app proves control of the shared identity to mint its own
62
+ * session.
119
63
  *
120
64
  * Throws if no shared identity exists (native-only; the shared keychain is
121
65
  * unavailable on web).
@@ -149,9 +93,11 @@ export declare class SignatureService {
149
93
  *
150
94
  * The envelope is self-issued: `issuer` equals `subject` (the signer's DID).
151
95
  * The signature covers the canonical JSON of every field EXCEPT `publicKey`
152
- * and `signature` (see {@link signedRecordSigningInput}); `alg` is
153
- * `ES256K-DER-SHA256` (secp256k1 over the SHA-256 of the canonical bytes,
154
- * DER-encoded), the same scheme this service uses everywhere else.
96
+ * and `signature`; `alg` is `ES256K-DER-SHA256` (secp256k1 over the SHA-256 of
97
+ * the canonical bytes, DER-encoded). The cryptography is delegated to the
98
+ * protocol's {@link signEnvelope}, which derives the (uncompressed-hex)
99
+ * `publicKey` from the stored device key — identical to the registered
100
+ * verification method.
155
101
  *
156
102
  * Requires a stored identity (native secure storage); throws if none exists.
157
103
  *
@@ -165,8 +111,8 @@ export declare class SignatureService {
165
111
  * fields.
166
112
  *
167
113
  * Identical to {@link signRecord} (self-issued: `issuer === subject`; same
168
- * `ES256K-DER-SHA256` scheme over {@link signedRecordSigningInput}) but
169
- * `version` is `2` and the signed bytes additionally cover the chain fields:
114
+ * `ES256K-DER-SHA256` scheme) but `version` is `2` and the signed bytes
115
+ * additionally cover the chain fields:
170
116
  *
171
117
  * @param type - The record category.
172
118
  * @param subject - The subject DID the record is about (also the issuer).
@@ -186,17 +132,5 @@ export declare class SignatureService {
186
132
  collection: string;
187
133
  rkey: string;
188
134
  }): Promise<SignedRecordEnvelope>;
189
- /**
190
- * Verify a signed-record envelope: recompute the canonical signing input from
191
- * the envelope's own fields and check the signature against the envelope's
192
- * `publicKey`.
193
- *
194
- * Note: this confirms the signature is internally consistent with the
195
- * embedded `publicKey`. It does NOT establish that `publicKey` is an
196
- * authorized verification method for `subject` — that authorization check is
197
- * the server's responsibility (it asserts the key is a current verification
198
- * method on the subject's DID).
199
- */
200
- static verifyRecord(envelope: SignedRecordEnvelope): Promise<boolean>;
201
135
  }
202
136
  export default SignatureService;
@@ -42,7 +42,7 @@ export type { CanonicalUserHandleInput, UserHandleInput } from './utils/userHand
42
42
  export { normalizeProfileLinks } from './utils/profileLinks';
43
43
  export type { ProfileLink, ProfileLinkMetadata } from './utils/profileLinks';
44
44
  export type { PublicApplication, ConnectedApp, } from './mixins/OxyServices.connectedApps';
45
- export type { AccountKind, AccountRelationship, AccountRole, AccountMemberStatus, AccountMemberSource, AccountMember, AccountNode, AccountCredentialType, AccountCredentialEnvironment, AccountCredentialStatus, AccountCredential, AccountCredentialWithSecret, RotateAccountCredentialResult, ListAccountsOptions, CreateAccountInput, UpdateAccountInput, InviteAccountMemberInput, UpdateAccountMemberInput, TransferAccountOwnershipInput, CreateAccountCredentialInput, AccountSuccessResult, Application, ApplicationType, ApplicationStatus, ApplicationCredential, ApplicationCredentialType, ApplicationCredentialStatus, ApplicationEnvironment, CreateApplicationInput, UpdateApplicationInput, CreateApplicationCredentialInput, ApplicationCredentialWithSecret, RotateApplicationCredentialResult, ApplicationUsagePeriod, ApplicationUsageSummary, ApplicationUsageByDay, ApplicationUsageByEndpoint, ApplicationUsageStats, } from './mixins/OxyServices.accounts';
45
+ export type { AccountKind, AccountRelationship, AccountRole, AccountMemberStatus, AccountMemberSource, AccountMember, AccountNode, AccountCredentialType, AccountCredentialEnvironment, AccountCredentialStatus, AccountCredential, AccountCredentialWithSecret, RotateAccountCredentialResult, ListAccountsOptions, CreateAccountInput, UpdateAccountInput, InviteAccountMemberInput, UpdateAccountMemberInput, TransferAccountOwnershipInput, CreateAccountCredentialInput, AccountSuccessResult, SwitchAccountResult, Application, ApplicationType, ApplicationStatus, ApplicationCredential, ApplicationCredentialType, ApplicationCredentialStatus, ApplicationEnvironment, CreateApplicationInput, UpdateApplicationInput, CreateApplicationCredentialInput, ApplicationCredentialWithSecret, RotateApplicationCredentialResult, ApplicationUsagePeriod, ApplicationUsageSummary, ApplicationUsageByDay, ApplicationUsageByEndpoint, ApplicationUsageStats, } from './mixins/OxyServices.accounts';
46
46
  export type { ReputationCategory, TrustTier, ReputationTransactionStatus, ReputationTargetEntityType, ReputationDisputeStatus, ReputationInfluenceContext, ReputationTransaction, ReputationBalanceBreakdown, ReputationInfluence, ReputationReliability, ReputationBalance, ReputationDispute, ReputationRule, ReputationLeaderboardEntry, ReputationInfluenceResult, ReverseReputationTransactionResult, AwardReputationInput, CreateReputationDisputeInput, ResolveReputationDisputeInput, UpsertReputationRuleInput, ReverseReputationTransactionInput, } from './mixins/OxyServices.reputation';
47
47
  export { buildUserDid } from './mixins/OxyServices.identity';
48
48
  export type { IdentityRecordType, UnlinkableAuthMethodType, LinkAuthMethodResult, PublishRecordResult, VerifyRecordResult, VerifyDomainResult, RemoveDomainResult, } from './mixins/OxyServices.identity';
@@ -56,14 +56,13 @@ export type { ClientSession, StorageKeys, MinimalUserData, SessionLoginResponse,
56
56
  export type { RefreshAllResponse, RefreshAllAccount, RefreshAllAccountUser, RefreshCookieResponse, } from './models/interfaces';
57
57
  export { KeyManager, IdentityAlreadyExistsError, IdentityPersistError, } from './crypto/keyManager';
58
58
  export type { KeyPair } from './crypto/keyManager';
59
- export { SignatureService, signedRecordSigningInput, computeRecordId } from './crypto/signatureService';
60
- export type { SignedMessage, AuthChallenge, SignedRecordSigningFields } from './crypto/signatureService';
61
- export { canonicalize } from './crypto/canonicalJson';
59
+ export { SignatureService } from './crypto/signatureService';
60
+ export type { SignedMessage, AuthChallenge } from './crypto/signatureService';
62
61
  export { RecoveryPhraseService } from './crypto/recoveryPhrase';
63
62
  export type { RecoveryPhraseResult } from './crypto/recoveryPhrase';
64
63
  export { DeviceManager } from './utils/deviceManager';
65
64
  export type { DeviceFingerprint, StoredDeviceInfo } from './utils/deviceManager';
66
- export type { OxyConfig, PrivacySettings, NotificationPreferences, UserPreferences, User, LoginResponse, Notification, Wallet, Transaction, BlockedUser, RestrictedUser, TransferFundsRequest, PurchaseRequest, WithdrawalRequest, TransactionResponse, PaginationInfo, SearchProfilesResponse, ApiError, PaymentMethod, PaymentRequest, PaymentResponse, AnalyticsData, FollowerDetails, ContentViewer, FileMetadata, FileUploadResponse, FileListResponse, FileUpdateRequest, FileDeleteResponse, RNFileDescriptor, AssetUploadInput, FileVisibility, AssetLink, AssetMetadata, AssetVariant, Asset, AssetInitRequest, AssetInitResponse, AssetCompleteRequest, AssetLinkRequest, AssetUnlinkRequest, AssetUrlResponse, AssetDeleteSummary, AssetUpdateVisibilityRequest, AssetUpdateVisibilityResponse, AccountStorageCategoryUsage, AccountStorageUsageResponse, SecurityEventType, SecurityEventSeverity, SecurityActivity, SecurityActivityResponse, AssetUploadProgress, DeviceSession, DeviceSessionsResponse, DeviceSessionLogoutResponse, UpdateDeviceNameResponse, } from './models/interfaces';
65
+ export type { OxyConfig, PrivacySettings, NotificationPreferences, UserPreferences, User, LoginResponse, Notification, Wallet, Transaction, BlockedUser, RestrictedUser, TransferFundsRequest, PurchaseRequest, WithdrawalRequest, TransactionResponse, PaginationInfo, SearchProfilesResponse, ApiError, PaymentMethod, PaymentRequest, PaymentResponse, AnalyticsData, FollowerDetails, ContentViewer, FileMetadata, FileUploadResponse, FileListResponse, FileUpdateRequest, FileDeleteResponse, RNFileDescriptor, AssetUploadInput, FileVisibility, AssetLink, AssetMetadata, AssetVariant, Asset, AssetInitRequest, AssetInitResponse, AssetCompleteRequest, AssetLinkRequest, AssetUnlinkRequest, AssetUrlResponse, AssetDeleteSummary, AssetUpdateVisibilityRequest, AssetUpdateVisibilityResponse, ServiceAssetMetadata, AccountStorageCategoryUsage, AccountStorageUsageResponse, SecurityEventType, SecurityEventSeverity, SecurityActivity, SecurityActivityResponse, AssetUploadProgress, DeviceSession, DeviceSessionsResponse, DeviceSessionLogoutResponse, UpdateDeviceNameResponse, } from './models/interfaces';
67
66
  export { SECURITY_EVENT_SEVERITY_MAP } from './models/interfaces';
68
67
  export { TopicType, TopicSource } from './models/Topic';
69
68
  export type { TopicData, TopicTranslation } from './models/Topic';
@@ -25,11 +25,14 @@
25
25
  * member `_id`, and credentials by their `credentialId`. Never by name, slug, or
26
26
  * handle.
27
27
  *
28
- * NOTE: acting-as (delegated identity) is NOT part of this mixin — `setActingAs`
29
- * / `getActingAs` live on `OxyServices.base` and `verifyActingAs` on the utility
30
- * mixin (it verifies against `GET /accounts/verify-acting-as`).
28
+ * SWITCHING INTO AN ACCOUNT: `switchToAccount(accountId)` mints a REAL session
29
+ * for the target account and plants it as the active session — there is no
30
+ * per-request "acting-as" header. Identity is carried by the session/token, not
31
+ * a delegation header, so a switch propagates through reload and `refresh-all`
32
+ * exactly like a login.
31
33
  */
32
34
  import type { User } from '../models/interfaces';
35
+ import type { SessionLoginResponse } from '../models/session';
33
36
  import type { OxyServicesBase } from '../OxyServices.base';
34
37
  /**
35
38
  * Account classification, orthogonal to the federation `type`
@@ -381,6 +384,28 @@ export interface ApplicationUsageStats {
381
384
  export interface AccountSuccessResult {
382
385
  success: boolean;
383
386
  }
387
+ /**
388
+ * Result of {@link OxyServicesAccountsMixin.switchToAccount} — the freshly
389
+ * minted session for the target account, in the SAME shape the canonical login
390
+ * / `claimSessionByToken` responses use (`SessionLoginResponse`), plus the
391
+ * device-local refresh-cookie slot index.
392
+ *
393
+ * `accessToken` is the first access token for the new session (already planted
394
+ * as the active token by `switchToAccount`). The refresh token is NOT in the
395
+ * body — the server sets it as the httpOnly `oxy_rt_<authuser>` cookie, which
396
+ * joins the device multi-account set so the switched session survives reload and
397
+ * propagates cross-domain via `/auth/refresh-all`. `user` is the target account.
398
+ */
399
+ export interface SwitchAccountResult extends SessionLoginResponse {
400
+ /**
401
+ * The device-local refresh-cookie slot index (`oxy_rt_<authuser>`) the server
402
+ * assigned to the minted session. Surfaced so the consumer can register the
403
+ * new session in its device multi-account set exactly like a login response.
404
+ * Absent only when the server could not set the cookie (best-effort — the
405
+ * switch itself still succeeds).
406
+ */
407
+ authuser?: number;
408
+ }
384
409
  export declare function OxyServicesAccountsMixin<T extends typeof OxyServicesBase>(Base: T): {
385
410
  new (...args: any[]): {
386
411
  /**
@@ -399,6 +424,44 @@ export declare function OxyServicesAccountsMixin<T extends typeof OxyServicesBas
399
424
  * @param accountId - The account's Mongo `_id`.
400
425
  */
401
426
  getAccount(accountId: string): Promise<AccountNode>;
427
+ /**
428
+ * Switch the active session INTO a managed account.
429
+ *
430
+ * Calls `POST /accounts/:id/switch` with the signed-in operator's bearer.
431
+ * The server authorises the operator (must hold `account:act_as` over the
432
+ * target, directly or inherited — else 403; 404 if missing/archived; 403 if
433
+ * the target is a personal account), then mints a REAL session for the
434
+ * target account and returns it in the canonical login / `claimSessionByToken`
435
+ * shape (`{ sessionId, deviceId, expiresAt, accessToken, user, authuser }`).
436
+ *
437
+ * Unlike the removed `X-Acting-As` delegation header, the returned session
438
+ * IS the new identity: this plants `accessToken` as the active token —
439
+ * exactly like `claimSessionByToken` / `verifyChallenge` — so every
440
+ * subsequent request authenticates as the target account.
441
+ *
442
+ * Joining the device multi-account set (so the switch survives a reload and
443
+ * propagates cross-domain via `/auth/refresh-all`) requires a SECOND call, to
444
+ * `POST /auth/session`, made here after the token is planted. The switch route
445
+ * lives at `/accounts/*`, OUTSIDE the `oxy_rt_<authuser>` cookie's `Path=/auth`
446
+ * scope, so the server never sees the device's existing slots from it and
447
+ * would clobber slot 0 (destroying the operator's own session). `/auth/session`
448
+ * runs where those cookies ARE visible, so the server allocates a NEW slot that
449
+ * coexists with the operator's and returns its `authuser`. This step is
450
+ * web-only (native multi-account uses stored sessions, not cookies) and
451
+ * best-effort — a failure leaves the in-session switch intact; the switched
452
+ * account simply won't survive a reload until the cookie is next established.
453
+ *
454
+ * After planting, the SDK's identity-scoped GET cache is fully cleared so
455
+ * every cached read re-fetches as the new account. (The consuming
456
+ * `OxyContext` additionally invalidates its React Query cache and updates
457
+ * session state from the returned `user`; this clears the SDK's own HTTP
458
+ * cache at the source — `setTokens` deliberately preserves the warm cache for
459
+ * same-user silent refreshes, so the sweep here is explicit.)
460
+ *
461
+ * @param accountId - The target account's Mongo `_id`.
462
+ * @returns The minted session (planted) plus the device `authuser` slot.
463
+ */
464
+ switchToAccount(accountId: string): Promise<SwitchAccountResult>;
402
465
  /**
403
466
  * Create a new (non-personal) account. The caller becomes its `owner`.
404
467
  * @param data - Account configuration: kind, optional parent, and profile.
@@ -622,8 +685,6 @@ export declare function OxyServicesAccountsMixin<T extends typeof OxyServicesBas
622
685
  hasValidToken(): boolean;
623
686
  getAccessToken(): string | null;
624
687
  getAccessTokenExpiry(): number | null;
625
- setActingAs(userId: string | null): void;
626
- getActingAs(): string | null;
627
688
  waitForAuth(timeoutMs?: number): Promise<boolean>;
628
689
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
629
690
  maxRetries?: number;
@@ -55,8 +55,6 @@ export declare function OxyServicesAnalyticsMixin<T extends typeof OxyServicesBa
55
55
  hasValidToken(): boolean;
56
56
  getAccessToken(): string | null;
57
57
  getAccessTokenExpiry(): number | null;
58
- setActingAs(userId: string | null): void;
59
- getActingAs(): string | null;
60
58
  waitForAuth(timeoutMs?: number): Promise<boolean>;
61
59
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
62
60
  maxRetries?: number;
@@ -91,8 +91,6 @@ export declare function OxyServicesAppDataMixin<T extends typeof OxyServicesBase
91
91
  hasValidToken(): boolean;
92
92
  getAccessToken(): string | null;
93
93
  getAccessTokenExpiry(): number | null;
94
- setActingAs(userId: string | null): void;
95
- getActingAs(): string | null;
96
94
  waitForAuth(timeoutMs?: number): Promise<boolean>;
97
95
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
98
96
  maxRetries?: number;
@@ -1,7 +1,17 @@
1
- import type { AccountStorageUsageResponse, AssetUploadInput, AssetUrlResponse, AssetVariant } from '../models/interfaces';
1
+ import type { AccountStorageUsageResponse, AssetUploadInput, AssetUrlResponse, AssetVariant, ServiceAssetMetadata } from '../models/interfaces';
2
2
  import type { OxyServicesBase } from '../OxyServices.base';
3
3
  export declare function OxyServicesAssetsMixin<T extends typeof OxyServicesBase>(Base: T): {
4
4
  new (...args: any[]): {
5
+ /**
6
+ * Service-token request, implemented by the auth mixin earlier in the
7
+ * composition pipeline (see `mixins/index.ts`). The assets mixin is typed
8
+ * against `OxyServicesBase`, which does not carry the auth mixin's methods,
9
+ * so this `declare` surfaces the inherited runtime method to TypeScript
10
+ * without re-implementing it. Used by
11
+ * {@link getServiceAssetMetadataByIds} to authenticate the server-to-server
12
+ * `/assets/service/by-ids` bulk fetch with a bearer service token.
13
+ */
14
+ makeServiceRequest: <R = unknown>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: unknown, userId?: string) => Promise<R>;
5
15
  /**
6
16
  * Delete file
7
17
  */
@@ -49,6 +59,37 @@ export declare function OxyServicesAssetsMixin<T extends typeof OxyServicesBase>
49
59
  * Get download URLs for multiple files efficiently
50
60
  */
51
61
  getFileDownloadUrls(fileIds: string[], context?: string): Promise<Record<string, string>>;
62
+ /**
63
+ * Resolve many Oxy asset ids to their content-addressed metadata in one
64
+ * round-trip per chunk via `POST /assets/service/by-ids` (body `{ ids }`).
65
+ *
66
+ * Returns each asset's `sha256`, `mime`, byte `size`, and `status` — built
67
+ * for server-to-server callers (e.g. Mention's MTN Protocol blob-ref
68
+ * resolution) that need the content hash for an asset id. Ids are
69
+ * deduplicated and validated (empty/blank ids dropped) before being split
70
+ * into chunks of {@link SERVICE_ASSET_METADATA_CHUNK_SIZE} (the server-side
71
+ * cap). The server omits unknown/deleted ids from each chunk's `data`, so
72
+ * the merged result may be shorter than the requested id list and the caller
73
+ * is expected to map by `id`.
74
+ *
75
+ * **Service-token auth (required).** `/assets/service/by-ids` is guarded by
76
+ * `serviceAuthMiddleware` + the `files:read` scope and is called via
77
+ * `makeServiceRequest`, which attaches `Authorization: Bearer <serviceToken>`
78
+ * (the same client that calls `POST /assets/service/cache`). The calling
79
+ * client MUST be service-configured (`configureServiceAuth(apiKey,
80
+ * apiSecret)`) before invoking this method; otherwise `getServiceToken()`
81
+ * throws because no credentials are available. A plain user-session request
82
+ * is rejected by the route's service-auth guard.
83
+ *
84
+ * Resilience: chunks are independent. A failed chunk is logged and skipped —
85
+ * the method returns every entry that resolved successfully rather than
86
+ * discarding the whole call on one chunk's failure. An empty/whitespace-only
87
+ * input resolves immediately with `[]` and performs no network call.
88
+ *
89
+ * Not cached at the SDK layer: it's a POST keyed on a multi-id body (low hit
90
+ * rate), mirroring the sibling service/POST methods which never cache.
91
+ */
92
+ getServiceAssetMetadataByIds(ids: string[]): Promise<ServiceAssetMetadata[]>;
52
93
  /**
53
94
  * Upload raw file data
54
95
  */
@@ -135,8 +176,6 @@ export declare function OxyServicesAssetsMixin<T extends typeof OxyServicesBase>
135
176
  hasValidToken(): boolean;
136
177
  getAccessToken(): string | null;
137
178
  getAccessTokenExpiry(): number | null;
138
- setActingAs(userId: string | null): void;
139
- getActingAs(): string | null;
140
179
  waitForAuth(timeoutMs?: number): Promise<boolean>;
141
180
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
142
181
  maxRetries?: number;
@@ -570,8 +570,6 @@ export declare function OxyServicesAuthMixin<T extends typeof OxyServicesBase>(B
570
570
  hasValidToken(): boolean;
571
571
  getAccessToken(): string | null;
572
572
  getAccessTokenExpiry(): number | null;
573
- setActingAs(userId: string | null): void;
574
- getActingAs(): string | null;
575
573
  waitForAuth(timeoutMs?: number): Promise<boolean>;
576
574
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
577
575
  maxRetries?: number;
@@ -48,7 +48,7 @@
48
48
  * platform-agnostic; deriving the current user's DID requires an authenticated
49
49
  * session.
50
50
  */
51
- import type { CredentialIssueResult, CredentialListResult, CredentialStatus, CredentialVerifyResult, ExportAttestation, PersonhoodStatusResult, PublicCard, RealLifeAttestationResult, SignedPublicCard, SignedRecordEnvelope, SignedRecordType, ValidationRequestSummary, ValidationVerdict, ValidationVoteResult, VerifiableCredentialResponse, VouchResult } from '@oxyhq/contracts';
51
+ import type { CredentialIssueResult, CredentialListResult, CredentialStatus, CredentialVerifyResult, ExportAttestation, OxySignedRecordType, PersonhoodStatusResult, PublicCard, RealLifeAttestationResult, SignedPublicCard, SignedRecordEnvelope, ValidationRequestSummary, ValidationVerdict, ValidationVoteResult, VerifiableCredentialResponse, VouchResult } from '@oxyhq/contracts';
52
52
  import type { OxyServicesBase } from '../OxyServices.base';
53
53
  /**
54
54
  * A {@link SignedPublicCard} augmented with the client's verification verdict.
@@ -132,7 +132,7 @@ export declare function parseAttestPayload(raw: string): ParsedAttestPayload | n
132
132
  * key, matching the server which omits absent keys entirely) and checks the
133
133
  * `ES256K-DER-SHA256` signature against `attestation.publicKey`.
134
134
  *
135
- * NEVER throws: `SignatureService.verify` already swallows malformed-input
135
+ * NEVER throws: `verifySignature` already swallows malformed-input
136
136
  * errors and returns `false`, and an absent attestation short-circuits to
137
137
  * `false`. A pure, reusable helper (Commons can call it on a cached card).
138
138
  *
@@ -456,7 +456,7 @@ export declare function OxyServicesCivicMixin<T extends typeof OxyServicesBase>(
456
456
  * @param collection - The AtProto-style collection namespace.
457
457
  * @param rkey - The AtProto-style record key within the collection.
458
458
  */
459
- _signMyCivicRecordV2(type: SignedRecordType, record: Record<string, unknown>, collection: string, rkey: string): Promise<SignedRecordEnvelope>;
459
+ _signMyCivicRecordV2(type: OxySignedRecordType, record: Record<string, unknown>, collection: string, rkey: string): Promise<SignedRecordEnvelope>;
460
460
  httpService: import("../HttpService").HttpService;
461
461
  cloudURL: string;
462
462
  config: import("../OxyServices.base").OxyConfig;
@@ -493,8 +493,6 @@ export declare function OxyServicesCivicMixin<T extends typeof OxyServicesBase>(
493
493
  hasValidToken(): boolean;
494
494
  getAccessToken(): string | null;
495
495
  getAccessTokenExpiry(): number | null;
496
- setActingAs(userId: string | null): void;
497
- getActingAs(): string | null;
498
496
  waitForAuth(timeoutMs?: number): Promise<boolean>;
499
497
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
500
498
  maxRetries?: number;
@@ -148,8 +148,6 @@ export declare function OxyServicesConnectedAppsMixin<T extends typeof OxyServic
148
148
  hasValidToken(): boolean;
149
149
  getAccessToken(): string | null;
150
150
  getAccessTokenExpiry(): number | null;
151
- setActingAs(userId: string | null): void;
152
- getActingAs(): string | null;
153
151
  waitForAuth(timeoutMs?: number): Promise<boolean>;
154
152
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
155
153
  maxRetries?: number;
@@ -83,8 +83,6 @@ export declare function OxyServicesContactsMixin<T extends typeof OxyServicesBas
83
83
  hasValidToken(): boolean;
84
84
  getAccessToken(): string | null;
85
85
  getAccessTokenExpiry(): number | null;
86
- setActingAs(userId: string | null): void;
87
- getActingAs(): string | null;
88
86
  waitForAuth(timeoutMs?: number): Promise<boolean>;
89
87
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
90
88
  maxRetries?: number;
@@ -85,8 +85,6 @@ export declare function OxyServicesDevicesMixin<T extends typeof OxyServicesBase
85
85
  hasValidToken(): boolean;
86
86
  getAccessToken(): string | null;
87
87
  getAccessTokenExpiry(): number | null;
88
- setActingAs(userId: string | null): void;
89
- getActingAs(): string | null;
90
88
  waitForAuth(timeoutMs?: number): Promise<boolean>;
91
89
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
92
90
  maxRetries?: number;
@@ -233,8 +233,6 @@ export declare function OxyServicesFeaturesMixin<T extends typeof OxyServicesBas
233
233
  hasValidToken(): boolean;
234
234
  getAccessToken(): string | null;
235
235
  getAccessTokenExpiry(): number | null;
236
- setActingAs(userId: string | null): void;
237
- getActingAs(): string | null;
238
236
  waitForAuth(timeoutMs?: number): Promise<boolean>;
239
237
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
240
238
  maxRetries?: number;
@@ -287,8 +287,6 @@ export declare function OxyServicesFedCMMixin<T extends typeof OxyServicesBase>(
287
287
  hasValidToken(): boolean;
288
288
  getAccessToken(): string | null;
289
289
  getAccessTokenExpiry(): number | null;
290
- setActingAs(userId: string | null): void;
291
- getActingAs(): string | null;
292
290
  waitForAuth(timeoutMs?: number): Promise<boolean>;
293
291
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
294
292
  maxRetries?: number;
@@ -23,10 +23,15 @@
23
23
  * on-device identity and throw on web (where `KeyManager.getPublicKey()` is
24
24
  * always `null`).
25
25
  */
26
- import type { AuthMethodsResponse, DidDocument, DomainVerificationInstructions, ExportBundle, SignedRecordEnvelope, VerifiedDomain } from '@oxyhq/contracts';
26
+ import type { AuthMethodsResponse, DidDocument, DomainVerificationInstructions, ExportBundle, OxySignedRecordType, SignedRecordEnvelope, VerifiedDomain } from '@oxyhq/contracts';
27
27
  import type { OxyServicesBase } from '../OxyServices.base';
28
- /** Record categories a client may sign and publish. */
29
- export type IdentityRecordType = SignedRecordEnvelope['type'];
28
+ /**
29
+ * Record categories a client may sign and publish to the Oxy store. The base
30
+ * envelope `type` is now an open string (any app may define its own records on
31
+ * the shared grammar); the Oxy identity store re-narrows it to the closed Oxy
32
+ * record set.
33
+ */
34
+ export type IdentityRecordType = OxySignedRecordType;
30
35
  /** Auth-method types that can be unlinked via {@link OxyServicesIdentityMixin}. */
31
36
  export type UnlinkableAuthMethodType = 'identity' | 'password' | 'google' | 'apple' | 'github';
32
37
  /**
@@ -230,8 +235,6 @@ export declare function OxyServicesIdentityMixin<T extends typeof OxyServicesBas
230
235
  hasValidToken(): boolean;
231
236
  getAccessToken(): string | null;
232
237
  getAccessTokenExpiry(): number | null;
233
- setActingAs(userId: string | null): void;
234
- getActingAs(): string | null;
235
238
  waitForAuth(timeoutMs?: number): Promise<boolean>;
236
239
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
237
240
  maxRetries?: number;
@@ -70,8 +70,6 @@ export declare function OxyServicesLanguageMixin<T extends typeof OxyServicesBas
70
70
  hasValidToken(): boolean;
71
71
  getAccessToken(): string | null;
72
72
  getAccessTokenExpiry(): number | null;
73
- setActingAs(userId: string | null): void;
74
- getActingAs(): string | null;
75
73
  waitForAuth(timeoutMs?: number): Promise<boolean>;
76
74
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
77
75
  maxRetries?: number;
@@ -87,8 +87,6 @@ export declare function OxyServicesLinksMixin<T extends typeof OxyServicesBase>(
87
87
  hasValidToken(): boolean;
88
88
  getAccessToken(): string | null;
89
89
  getAccessTokenExpiry(): number | null;
90
- setActingAs(userId: string | null): void;
91
- getActingAs(): string | null;
92
90
  waitForAuth(timeoutMs?: number): Promise<boolean>;
93
91
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
94
92
  maxRetries?: number;
@@ -53,8 +53,6 @@ export declare function OxyServicesLocationMixin<T extends typeof OxyServicesBas
53
53
  hasValidToken(): boolean;
54
54
  getAccessToken(): string | null;
55
55
  getAccessTokenExpiry(): number | null;
56
- setActingAs(userId: string | null): void;
57
- getActingAs(): string | null;
58
56
  waitForAuth(timeoutMs?: number): Promise<boolean>;
59
57
  withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
60
58
  maxRetries?: number;