@oxyhq/core 14.0.0 → 15.0.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.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/crypto/recoveryPhrase.js +32 -66
- package/dist/cjs/index.js +7 -0
- package/dist/cjs/mixins/OxyServices.deviceBoot.js +58 -0
- package/dist/cjs/mixins/OxyServices.reputation.js +47 -2
- package/dist/cjs/mixins/OxyServices.user.js +3 -4
- package/dist/cjs/session/accountProjection.js +4 -1
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/crypto/recoveryPhrase.js +32 -33
- package/dist/esm/index.js +7 -0
- package/dist/esm/mixins/OxyServices.deviceBoot.js +59 -1
- package/dist/esm/mixins/OxyServices.reputation.js +47 -2
- package/dist/esm/mixins/OxyServices.user.js +3 -4
- package/dist/esm/session/accountProjection.js +4 -1
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/crypto/recoveryPhrase.d.ts +6 -0
- package/dist/types/index.d.ts +0 -1
- package/dist/types/mixins/OxyServices.deviceBoot.d.ts +43 -1
- package/dist/types/mixins/OxyServices.identityBackup.d.ts +1 -1
- package/dist/types/mixins/OxyServices.reputation.d.ts +43 -276
- package/dist/types/mixins/OxyServices.user.d.ts +4 -1
- package/dist/types/models/interfaces.d.ts +6 -0
- package/package.json +3 -3
- package/src/crypto/__tests__/keyManager.test.ts +3 -2
- package/src/crypto/recoveryPhrase.ts +33 -34
- package/src/index.ts +5 -24
- package/src/mixins/OxyServices.deviceBoot.ts +67 -0
- package/src/mixins/OxyServices.identityBackup.ts +1 -1
- package/src/mixins/OxyServices.reputation.ts +88 -326
- package/src/mixins/OxyServices.user.ts +7 -3
- package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +59 -2
- package/src/mixins/__tests__/followGraphPagination.test.ts +21 -0
- package/src/mixins/__tests__/reputation.test.ts +115 -1
- package/src/models/interfaces.ts +2 -0
- package/src/session/accountProjection.ts +5 -1
- package/src/types/bip39.d.ts +0 -32
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
* for backing up and restoring user identities.
|
|
6
6
|
*
|
|
7
7
|
* Note: This module requires the polyfill to be loaded first (done via crypto/index.ts)
|
|
8
|
+
*
|
|
9
|
+
* Oxy recovery phrases are English-only, so the English wordlist is imported by
|
|
10
|
+
* its own subpath. Never reach for a package that exposes its wordlists through
|
|
11
|
+
* a barrel: `bip39`'s `_wordlists` hard-requires all ten languages, which put
|
|
12
|
+
* ~265 KB of unreachable wordlists into the initial chunk of every consuming
|
|
13
|
+
* app. Adding another language means one more subpath import, ideally lazy.
|
|
8
14
|
*/
|
|
9
15
|
/**
|
|
10
16
|
* HKDF context tag for the encrypted-backup key schedule (b3 Feature 1). Used as
|
package/dist/types/index.d.ts
CHANGED
|
@@ -41,7 +41,6 @@ export type { ProfileLink, ProfileLinkMetadata } from './utils/profileLinks';
|
|
|
41
41
|
export type { PublicApplication, ConnectedApp, } from './mixins/OxyServices.connectedApps';
|
|
42
42
|
export type { AccountKind, OrganizationCategory, 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';
|
|
43
43
|
export { ORGANIZATION_CATEGORIES } from './mixins/OxyServices.accounts';
|
|
44
|
-
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';
|
|
45
44
|
export { buildUserDid } from './mixins/OxyServices.identity';
|
|
46
45
|
export type { IdentityRecordType, UnlinkableAuthMethodType, LinkAuthMethodResult, PublishRecordResult, VerifyRecordResult, VerifyDomainResult, RemoveDomainResult, RotateKeyProof, RotateKeyOptions, RotateKeyResult, } from './mixins/OxyServices.identity';
|
|
47
46
|
export { parseIdPayload, parseAttestPayload, verifyPublicCardAttestation, } from './mixins/OxyServices.civic';
|
|
@@ -12,8 +12,13 @@
|
|
|
12
12
|
* This method carries NO persistence or token-planting side effects of its own;
|
|
13
13
|
* the cold boot / re-mint handler own persistence and `setTokens`, so the same
|
|
14
14
|
* primitive can be reused from either without double-planting.
|
|
15
|
+
*
|
|
16
|
+
* `provisionBackgroundCredential` is the mixin's second, adjacent call: it hands
|
|
17
|
+
* native background code (no JS runtime) its own non-rotating credential so that
|
|
18
|
+
* code never has to mint from — and therefore never rotates — the device secret
|
|
19
|
+
* JS depends on.
|
|
15
20
|
*/
|
|
16
|
-
import { type DeviceTokenMintResponse } from '@oxyhq/contracts';
|
|
21
|
+
import { type DeviceBackgroundCredentialResponse, type DeviceTokenMintResponse } from '@oxyhq/contracts';
|
|
17
22
|
import type { OxyServicesBase } from '../OxyServices.base';
|
|
18
23
|
/**
|
|
19
24
|
* The server's `401 account_not_on_device` for a PINNED mint: the requested
|
|
@@ -71,6 +76,43 @@ export declare function OxyServicesDeviceBootMixin<T extends typeof OxyServicesB
|
|
|
71
76
|
mintFromDeviceSecret(deviceId: string, deviceSecret: string, options?: {
|
|
72
77
|
accountId?: string;
|
|
73
78
|
}): Promise<DeviceTokenMintResponse>;
|
|
79
|
+
/**
|
|
80
|
+
* Provision a NON-rotating background credential for the caller's account on
|
|
81
|
+
* this device — the credential native background code (an Android widget
|
|
82
|
+
* worker, which runs with no JS runtime) presents to mint its own access
|
|
83
|
+
* tokens without any JS involvement.
|
|
84
|
+
*
|
|
85
|
+
* It exists precisely so background code never touches the device secret:
|
|
86
|
+
* `POST /session/device/token` ROTATES that secret on every mint (the
|
|
87
|
+
* presented one stays valid only for a short grace), so a worker minting
|
|
88
|
+
* from it would become a second writer of the value JS depends on and could
|
|
89
|
+
* silently sign the user out. The background credential is a separate,
|
|
90
|
+
* non-rotating value minted server-side, so the two lanes never contend.
|
|
91
|
+
*
|
|
92
|
+
* Bearer required and NO body: the server derives both the `deviceId` and
|
|
93
|
+
* the account from the validated bearer. This is the only way a background
|
|
94
|
+
* credential comes into existence, so background code can EXTEND a session
|
|
95
|
+
* the user established in-app but can never bootstrap one from nothing.
|
|
96
|
+
*
|
|
97
|
+
* Unlike the mint above this is NOT a control-plane call — it runs while a
|
|
98
|
+
* session is already live — so it takes the normal authenticated path: no
|
|
99
|
+
* `skipAuth` (a 401 should go through the ordinary re-mint lane) and no
|
|
100
|
+
* `bypassQueue` (nothing in the auth lane is parked awaiting it).
|
|
101
|
+
*
|
|
102
|
+
* There is deliberately no JS counterpart that MINTS from the returned
|
|
103
|
+
* credential: the native side owns that call, and a symmetric-looking JS
|
|
104
|
+
* method would be dead code plus a second implementation of the failure
|
|
105
|
+
* rules. The asymmetry is the design.
|
|
106
|
+
*
|
|
107
|
+
* @returns the provisioned credential, or `null` when the endpoint is absent
|
|
108
|
+
* (404). The API deploy leads the SDK release, so a client on a newer SDK
|
|
109
|
+
* than the server degrades to "no background session" quietly instead of
|
|
110
|
+
* surfacing an error. The status is read off the RAW rejection because
|
|
111
|
+
* `handleError` only preserves it for errors carrying `HttpService`'s
|
|
112
|
+
* annotations.
|
|
113
|
+
* @throws if the response does not match {@link deviceBackgroundCredentialResponseSchema}.
|
|
114
|
+
*/
|
|
115
|
+
provisionBackgroundCredential(): Promise<DeviceBackgroundCredentialResponse | null>;
|
|
74
116
|
httpService: import("../HttpService").HttpService;
|
|
75
117
|
cloudURL: string;
|
|
76
118
|
config: import("../OxyServices.base").OxyConfig;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Key schedule (from the recovery phrase; see
|
|
9
9
|
* {@link RecoveryPhraseService.deriveBackupMaterial}):
|
|
10
|
-
* seed =
|
|
10
|
+
* seed = mnemonicToSeed(phrase) // 64 bytes, UNCHANGED
|
|
11
11
|
* backupKey = HKDF(seed, 'oxy-identity-backup-v1', 'oxy-backup-encryption-key')
|
|
12
12
|
* lookupId = HKDF(seed, 'oxy-identity-backup-v1', 'oxy-backup-lookup-id') // hex
|
|
13
13
|
*
|
|
@@ -12,291 +12,54 @@
|
|
|
12
12
|
* their `active` transactions, augmented with a trust tier, capped influence
|
|
13
13
|
* weights, and reliability signals.
|
|
14
14
|
*
|
|
15
|
+
* A balance is served in TWO views (see `ReputationBalanceView`): the subject
|
|
16
|
+
* and platform staff get the whole thing, a third party gets the public trust
|
|
17
|
+
* signal only. The two are distinct types so a caller cannot read a field the
|
|
18
|
+
* server did not send them.
|
|
19
|
+
*
|
|
20
|
+
* EVERY type on this surface is owned by `@oxyhq/contracts`, which the API's
|
|
21
|
+
* serializers are annotated and validated against. This mixin declares none of
|
|
22
|
+
* them and re-exports none of them: consumers import the types straight from
|
|
23
|
+
* `@oxyhq/contracts`, so the wire shape has exactly one definition and a
|
|
24
|
+
* server-side change to a serializer cannot compile while the type still
|
|
25
|
+
* promises the old shape.
|
|
26
|
+
*
|
|
15
27
|
* Reference users by their Mongo `_id` (or publicKey, which the API resolves),
|
|
16
28
|
* transactions by their `id`, and disputes by their `id`.
|
|
17
29
|
*/
|
|
30
|
+
import type { AwardReputationInput, CreateReputationDisputeInput, ReputationBalance, ReputationBalanceView, ReputationDispute, ReputationInfluenceContext, ReputationInfluenceResult, ReputationLeaderboardEntry, ReputationRule, ReputationTransaction, ResolveReputationDisputeInput, ReverseReputationTransactionInput, ReverseReputationTransactionResult, UpsertReputationRuleInput } from '@oxyhq/contracts';
|
|
18
31
|
import type { OxyServicesBase } from '../OxyServices.base';
|
|
19
|
-
import type { User } from '../models/interfaces';
|
|
20
|
-
/**
|
|
21
|
-
* Category bucket a reputation transaction falls into. Drives the per-category
|
|
22
|
-
* balance breakdown.
|
|
23
|
-
*/
|
|
24
|
-
export type ReputationCategory = 'content' | 'social' | 'trust' | 'moderation' | 'physical' | 'penalty' | 'other';
|
|
25
|
-
/** Trust tiers, lowest → highest (plus the punitive `restricted`). */
|
|
26
|
-
export type TrustTier = 'new' | 'trusted' | 'high_trust' | 'verified' | 'restricted';
|
|
27
|
-
/**
|
|
28
|
-
* Transaction lifecycle status. Only `active` transactions count toward the
|
|
29
|
-
* balance; `disputed` still counts until the dispute resolves; `reversed` and
|
|
30
|
-
* `voided` are excluded.
|
|
31
|
-
*/
|
|
32
|
-
export type ReputationTransactionStatus = 'active' | 'disputed' | 'reversed' | 'voided';
|
|
33
|
-
/** Kind of entity a transaction may target. */
|
|
34
|
-
export type ReputationTargetEntityType = 'post' | 'comment' | 'report' | 'purchase' | 'event' | 'check_in' | 'manual_review' | 'user' | 'other';
|
|
35
|
-
/** Dispute lifecycle status. */
|
|
36
|
-
export type ReputationDisputeStatus = 'open' | 'accepted' | 'rejected' | 'needs_review';
|
|
37
|
-
/** Influence context selecting which capped weight axis to return. */
|
|
38
|
-
export type ReputationInfluenceContext = 'default' | 'report' | 'moderation' | 'ranking';
|
|
39
|
-
/**
|
|
40
|
-
* A single immutable entry in the reputation ledger. Ids are emitted as strings
|
|
41
|
-
* and dates as ISO strings by the API.
|
|
42
|
-
*/
|
|
43
|
-
export interface ReputationTransaction {
|
|
44
|
-
/** The transaction's Mongo `_id` as a string. */
|
|
45
|
-
id: string;
|
|
46
|
-
/** Subject of the reputation change — the user whose balance moves. */
|
|
47
|
-
userId: string;
|
|
48
|
-
/** Signed point delta. Positive awards, negative penalties/reversals. */
|
|
49
|
-
points: number;
|
|
50
|
-
/** The rule/action key that produced this transaction (e.g. `post_created`). */
|
|
51
|
-
actionType: string;
|
|
52
|
-
/** Category bucket the points fall into. */
|
|
53
|
-
category: ReputationCategory;
|
|
54
|
-
/** Canonical source application that reported the action, if any. */
|
|
55
|
-
applicationId?: string;
|
|
56
|
-
/** The specific credential used by the source application, if any. */
|
|
57
|
-
credentialId?: string;
|
|
58
|
-
/** Opaque id of the originating action in the source system (idempotency key). */
|
|
59
|
-
sourceActionId?: string;
|
|
60
|
-
/** Source-system action type (e.g. `report_confirmed`, `event_check_in`). */
|
|
61
|
-
sourceActionType?: string;
|
|
62
|
-
/** Id of the entity the action targeted (post id, report id, etc.). */
|
|
63
|
-
targetEntityId?: string;
|
|
64
|
-
/** Kind of the targeted entity. */
|
|
65
|
-
targetEntityType?: ReputationTargetEntityType;
|
|
66
|
-
/** Lifecycle status — only `active` transactions count toward the balance. */
|
|
67
|
-
status: ReputationTransactionStatus;
|
|
68
|
-
/**
|
|
69
|
-
* Set ONLY on a compensating reversal transaction; references the original
|
|
70
|
-
* transaction it reverses. The original carries `status: 'reversed'`.
|
|
71
|
-
*/
|
|
72
|
-
reversedTransactionId?: string;
|
|
73
|
-
/** Human-readable reason / note. */
|
|
74
|
-
reason?: string;
|
|
75
|
-
/** Free-form structured metadata from the source system. */
|
|
76
|
-
metadata?: Record<string, unknown>;
|
|
77
|
-
/** The user who caused this change (the liker, the reporting user, staff). */
|
|
78
|
-
createdByUserId?: string;
|
|
79
|
-
/** Staff/service principal who reviewed (reversed/voided) this transaction. */
|
|
80
|
-
reviewedByUserId?: string;
|
|
81
|
-
/** ISO timestamp the transaction was reviewed at, if reviewed. */
|
|
82
|
-
reviewedAt?: string;
|
|
83
|
-
/** ISO creation timestamp. */
|
|
84
|
-
createdAt: string;
|
|
85
|
-
/** ISO last-update timestamp. */
|
|
86
|
-
updatedAt: string;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Per-category sums of a user's ACTIVE transactions. `penalties` is the
|
|
90
|
-
* absolute sum of every negative-point transaction; the named buckets carry the
|
|
91
|
-
* signed sum of transactions in that category.
|
|
92
|
-
*/
|
|
93
|
-
export interface ReputationBalanceBreakdown {
|
|
94
|
-
content: number;
|
|
95
|
-
social: number;
|
|
96
|
-
trust: number;
|
|
97
|
-
moderation: number;
|
|
98
|
-
physical: number;
|
|
99
|
-
penalties: number;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Capped influence weights (#219). Every weight is clamped to a configured
|
|
103
|
-
* range; restricted users are floored on every axis. Downstream systems
|
|
104
|
-
* (ranking, moderation, reporting) consume these to weight a user's
|
|
105
|
-
* contributions without letting any single user dominate.
|
|
106
|
-
*/
|
|
107
|
-
export interface ReputationInfluence {
|
|
108
|
-
/** General-purpose trust weight derived from the lifetime total. */
|
|
109
|
-
defaultWeight: number;
|
|
110
|
-
/** Weight applied to this user's reports (scales with report accuracy). */
|
|
111
|
-
reportWeight: number;
|
|
112
|
-
/** Weight applied to this user's moderation actions (scales with tier). */
|
|
113
|
-
moderationWeight: number;
|
|
114
|
-
/** Damped weight applied to this user's ranking feedback. */
|
|
115
|
-
rankingFeedbackWeight: number;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Reliability signals (#219) derived from the user's moderation track record in
|
|
119
|
-
* the ledger.
|
|
120
|
-
*/
|
|
121
|
-
export interface ReputationReliability {
|
|
122
|
-
/** Count of active transactions stamped `report_confirmed`. */
|
|
123
|
-
accurateReports: number;
|
|
124
|
-
/** Count of active transactions stamped `report_rejected`. */
|
|
125
|
-
rejectedReports: number;
|
|
126
|
-
/** accurate / (accurate + rejected), or the neutral 0.5 when no history. */
|
|
127
|
-
reportAccuracyScore: number;
|
|
128
|
-
/** Smoothed 0..1 abuse signal; high values force the `restricted` tier. */
|
|
129
|
-
abuseScore: number;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Cached, recomputable snapshot of a user's reputation. Shape mirrors the
|
|
133
|
-
* `/reputation/:userId/balance` response (which omits internal `lastTransactionId`
|
|
134
|
-
* and `createdAt`).
|
|
135
|
-
*/
|
|
136
|
-
export interface ReputationBalance {
|
|
137
|
-
userId: string;
|
|
138
|
-
/** Net lifetime total across all active transactions. */
|
|
139
|
-
total: number;
|
|
140
|
-
/** Sum of positive points only. */
|
|
141
|
-
positive: number;
|
|
142
|
-
/** Sum of negative points only (a negative number). */
|
|
143
|
-
negative: number;
|
|
144
|
-
breakdown: ReputationBalanceBreakdown;
|
|
145
|
-
trustTier: TrustTier;
|
|
146
|
-
influence: ReputationInfluence;
|
|
147
|
-
reliability: ReputationReliability;
|
|
148
|
-
/** ISO timestamp the snapshot was last recomputed at. */
|
|
149
|
-
recalculatedAt: string;
|
|
150
|
-
/** ISO last-update timestamp. */
|
|
151
|
-
updatedAt: string;
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* A user-initiated dispute against a specific reputation transaction. Ids are
|
|
155
|
-
* strings and dates ISO strings.
|
|
156
|
-
*/
|
|
157
|
-
export interface ReputationDispute {
|
|
158
|
-
/** The dispute's Mongo `_id` as a string. */
|
|
159
|
-
id: string;
|
|
160
|
-
/** The transaction being disputed. */
|
|
161
|
-
transactionId: string;
|
|
162
|
-
/** The user raising the dispute. */
|
|
163
|
-
userId: string;
|
|
164
|
-
/** Why the user believes the transaction is wrong. */
|
|
165
|
-
reason: string;
|
|
166
|
-
status: ReputationDisputeStatus;
|
|
167
|
-
/** Optional supporting evidence (URLs / references). */
|
|
168
|
-
evidence?: string[];
|
|
169
|
-
/** ISO timestamp the dispute was resolved at, if resolved. */
|
|
170
|
-
resolvedAt?: string;
|
|
171
|
-
/** Staff principal who resolved the dispute, if resolved. */
|
|
172
|
-
resolvedByUserId?: string;
|
|
173
|
-
/** ISO creation timestamp. */
|
|
174
|
-
createdAt: string;
|
|
175
|
-
/** ISO last-update timestamp. */
|
|
176
|
-
updatedAt: string;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* A configurable reputation award/penalty rule. The `/reputation/rules`
|
|
180
|
-
* response shape: `id` is the rule's `_id`; no timestamps are emitted.
|
|
181
|
-
*/
|
|
182
|
-
export interface ReputationRule {
|
|
183
|
-
/** The rule's Mongo `_id` as a string. */
|
|
184
|
-
id: string;
|
|
185
|
-
/** Unique action key (e.g. `post_created`). */
|
|
186
|
-
actionType: string;
|
|
187
|
-
/** Signed points the rule awards (may be negative for penalties). */
|
|
188
|
-
points: number;
|
|
189
|
-
/** Category the resulting transaction is filed under. */
|
|
190
|
-
category: ReputationCategory;
|
|
191
|
-
description: string;
|
|
192
|
-
/** Per (user, actionType) cooldown in minutes; 0 disables the cooldown. */
|
|
193
|
-
cooldownInMinutes: number;
|
|
194
|
-
isEnabled: boolean;
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* A single leaderboard entry. `user` is the populated user document the API
|
|
198
|
-
* returns alongside the lifetime total, derived trust tier, and 1-based rank.
|
|
199
|
-
*/
|
|
200
|
-
export interface ReputationLeaderboardEntry {
|
|
201
|
-
/** The populated user (id, username, name, avatar, publicKey). */
|
|
202
|
-
user: Pick<User, 'id' | 'username' | 'name' | 'avatar' | 'publicKey'> & Partial<User>;
|
|
203
|
-
/** Net lifetime total. */
|
|
204
|
-
total: number;
|
|
205
|
-
/** Derived trust tier. */
|
|
206
|
-
trustTier: TrustTier;
|
|
207
|
-
/** 1-based rank within the leaderboard (`offset + index + 1`). */
|
|
208
|
-
rank: number;
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* Result of `getReputationInfluence` — the requested context, the single capped
|
|
212
|
-
* weight for that context, and the full influence block.
|
|
213
|
-
*/
|
|
214
|
-
export interface ReputationInfluenceResult {
|
|
215
|
-
context: ReputationInfluenceContext;
|
|
216
|
-
weight: number;
|
|
217
|
-
influence: ReputationInfluence;
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Result of `reverseReputationTransaction` — the now-`reversed` original plus
|
|
221
|
-
* the compensating `active` reversal entry.
|
|
222
|
-
*/
|
|
223
|
-
export interface ReverseReputationTransactionResult {
|
|
224
|
-
original: ReputationTransaction;
|
|
225
|
-
reversal: ReputationTransaction;
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Input for `awardReputation`. Awarding is restricted to service tokens (the
|
|
229
|
-
* canonical path) and platform staff; regular users may NOT award reputation.
|
|
230
|
-
* When called with a service token, `applicationId` / `credentialId` are
|
|
231
|
-
* resolved from the token and any client-supplied values are ignored.
|
|
232
|
-
*/
|
|
233
|
-
export interface AwardReputationInput {
|
|
234
|
-
/** The subject whose reputation changes (`_id` or publicKey). */
|
|
235
|
-
userId: string;
|
|
236
|
-
/** The enabled rule's action key (e.g. `post_created`). */
|
|
237
|
-
actionType: string;
|
|
238
|
-
/** Source application id (ignored for service tokens). */
|
|
239
|
-
applicationId?: string;
|
|
240
|
-
/** Source credential id (ignored for service tokens). */
|
|
241
|
-
credentialId?: string;
|
|
242
|
-
/** Opaque originating-action id used as the idempotency key. */
|
|
243
|
-
sourceActionId?: string;
|
|
244
|
-
/** Source-system action type. */
|
|
245
|
-
sourceActionType?: string;
|
|
246
|
-
/** Id of the targeted entity. */
|
|
247
|
-
targetEntityId?: string;
|
|
248
|
-
/** Kind of the targeted entity. */
|
|
249
|
-
targetEntityType?: ReputationTargetEntityType;
|
|
250
|
-
/** Optional human-readable reason (max 500 chars). */
|
|
251
|
-
reason?: string;
|
|
252
|
-
/** Free-form structured metadata from the source system. */
|
|
253
|
-
metadata?: Record<string, unknown>;
|
|
254
|
-
}
|
|
255
|
-
/** Input for `createReputationDispute`. The disputer is the authenticated user. */
|
|
256
|
-
export interface CreateReputationDisputeInput {
|
|
257
|
-
/** The transaction being disputed. */
|
|
258
|
-
transactionId: string;
|
|
259
|
-
/** Why the transaction is believed to be wrong (1..1000 chars). */
|
|
260
|
-
reason: string;
|
|
261
|
-
/** Optional supporting evidence (URLs / references; max 20). */
|
|
262
|
-
evidence?: string[];
|
|
263
|
-
}
|
|
264
|
-
/** Input for `resolveReputationDispute` (staff). */
|
|
265
|
-
export interface ResolveReputationDisputeInput {
|
|
266
|
-
/** Accepting reverses the disputed transaction; rejecting restores it. */
|
|
267
|
-
status: 'accepted' | 'rejected';
|
|
268
|
-
}
|
|
269
|
-
/** Input for `upsertReputationRule` (staff). Keyed by `actionType`. */
|
|
270
|
-
export interface UpsertReputationRuleInput {
|
|
271
|
-
/** Unique action key (e.g. `post_created`). */
|
|
272
|
-
actionType: string;
|
|
273
|
-
/** Signed points the rule awards (may be negative). */
|
|
274
|
-
points: number;
|
|
275
|
-
/** Category the resulting transaction is filed under. */
|
|
276
|
-
category: ReputationCategory;
|
|
277
|
-
/** Human-readable description (1..500 chars). */
|
|
278
|
-
description: string;
|
|
279
|
-
/** Per (user, actionType) cooldown in minutes; defaults to 0. */
|
|
280
|
-
cooldownInMinutes?: number;
|
|
281
|
-
/** Whether the rule is active; defaults to true. */
|
|
282
|
-
isEnabled?: boolean;
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Input for `reverseReputationTransaction` / `voidReputationTransaction`
|
|
286
|
-
* (staff). The reviewing principal is the authenticated user.
|
|
287
|
-
*/
|
|
288
|
-
export interface ReverseReputationTransactionInput {
|
|
289
|
-
/** Optional human-readable reason (max 500 chars). */
|
|
290
|
-
reason?: string;
|
|
291
|
-
}
|
|
292
32
|
export declare function OxyServicesReputationMixin<T extends typeof OxyServicesBase>(Base: T): {
|
|
293
33
|
new (...args: any[]): {
|
|
294
34
|
/**
|
|
295
|
-
* Get
|
|
296
|
-
*
|
|
35
|
+
* Get ANY user's reputation balance, in whichever view the server serves the
|
|
36
|
+
* caller.
|
|
37
|
+
*
|
|
38
|
+
* A third party gets `userId`, `total` and `trustTier` and nothing else, so
|
|
39
|
+
* the return type is a {@link ReputationBalanceView} union: narrow it with
|
|
40
|
+
* {@link isFullReputationBalance} before touching `breakdown`, `influence`
|
|
41
|
+
* or `reliability`. To read your OWN balance, call
|
|
42
|
+
* {@link getMyReputationBalance} instead — it returns the full shape with no
|
|
43
|
+
* narrowing.
|
|
44
|
+
*
|
|
297
45
|
* @param userId - The subject user's `_id` or publicKey.
|
|
298
46
|
*/
|
|
299
|
-
getReputationBalance(userId: string): Promise<
|
|
47
|
+
getReputationBalance(userId: string): Promise<ReputationBalanceView>;
|
|
48
|
+
/**
|
|
49
|
+
* Get the SIGNED-IN user's own reputation balance, in full.
|
|
50
|
+
*
|
|
51
|
+
* The subject view is the only one carrying `breakdown`, `influence` and
|
|
52
|
+
* `reliability`, and the subject is the common caller, so this is the
|
|
53
|
+
* ergonomic path: no id to pass, no narrowing to do.
|
|
54
|
+
*
|
|
55
|
+
* Throws rather than returning a half-populated object when the request was
|
|
56
|
+
* not authenticated as the subject — with no signed-in user, and when the
|
|
57
|
+
* server answered `200` with the public view anyway (which it does for an
|
|
58
|
+
* absent or lapsed token, since the endpoint's auth is optional). Both mean
|
|
59
|
+
* the private blocks are simply absent, and a thrown error is the only
|
|
60
|
+
* honest report of that.
|
|
61
|
+
*/
|
|
62
|
+
getMyReputationBalance(): Promise<ReputationBalance>;
|
|
300
63
|
/**
|
|
301
64
|
* Get the reputation leaderboard, ordered by lifetime total descending.
|
|
302
65
|
* @param limit - Page size (server-capped).
|
|
@@ -365,6 +128,10 @@ export declare function OxyServicesReputationMixin<T extends typeof OxyServicesB
|
|
|
365
128
|
/**
|
|
366
129
|
* Force a recompute of a user's balance snapshot from their active ledger
|
|
367
130
|
* (staff only). Invalidates cached reputation reads.
|
|
131
|
+
*
|
|
132
|
+
* Staff-gated, so the response is always the full subject view — no
|
|
133
|
+
* narrowing needed.
|
|
134
|
+
*
|
|
368
135
|
* @param userId - The subject user's `_id` or publicKey.
|
|
369
136
|
*/
|
|
370
137
|
recalculateReputation(userId: string): Promise<ReputationBalance>;
|
|
@@ -182,7 +182,10 @@ export declare function OxyServicesUserMixin<T extends typeof OxyServicesBase>(B
|
|
|
182
182
|
/**
|
|
183
183
|
* Get profiles similar to a given user, based on co-follower overlap.
|
|
184
184
|
*/
|
|
185
|
-
getSimilarProfiles(userId: string,
|
|
185
|
+
getSimilarProfiles(userId: string, limitOrParams?: number | {
|
|
186
|
+
limit?: number;
|
|
187
|
+
offset?: number;
|
|
188
|
+
}): Promise<User[]>;
|
|
186
189
|
/**
|
|
187
190
|
* Get user by ID.
|
|
188
191
|
*
|
|
@@ -215,6 +215,9 @@ export interface BlockedUser {
|
|
|
215
215
|
_id: string;
|
|
216
216
|
username: string;
|
|
217
217
|
avatar?: string;
|
|
218
|
+
name?: {
|
|
219
|
+
displayName?: string;
|
|
220
|
+
};
|
|
218
221
|
};
|
|
219
222
|
userId: string;
|
|
220
223
|
createdAt?: string;
|
|
@@ -228,6 +231,9 @@ export interface RestrictedUser {
|
|
|
228
231
|
_id: string;
|
|
229
232
|
username: string;
|
|
230
233
|
avatar?: string;
|
|
234
|
+
name?: {
|
|
235
|
+
displayName?: string;
|
|
236
|
+
};
|
|
231
237
|
};
|
|
232
238
|
userId: string;
|
|
233
239
|
createdAt?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxyhq/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "15.0.0",
|
|
4
4
|
"description": "OxyHQ SDK Foundation — API client, authentication, cryptographic identity, and shared utilities",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -115,9 +115,9 @@
|
|
|
115
115
|
"dependencies": {
|
|
116
116
|
"@noble/ciphers": "^1.3.0",
|
|
117
117
|
"@noble/hashes": "^1.8.0",
|
|
118
|
-
"@oxyhq/contracts": "^0.
|
|
118
|
+
"@oxyhq/contracts": "^0.20.0",
|
|
119
119
|
"@oxyhq/protocol": "^0.1.6",
|
|
120
|
-
"bip39": "^
|
|
120
|
+
"@scure/bip39": "^1.6.0",
|
|
121
121
|
"buffer": "^6.0.3",
|
|
122
122
|
"elliptic": "^6.6.1",
|
|
123
123
|
"invariant": "^2.2.4",
|
|
@@ -309,8 +309,9 @@ describe('KeyManager safety invariants', () => {
|
|
|
309
309
|
(KeyManager as unknown as { cachedPublicKey: unknown; cachedHasIdentity: unknown }).cachedHasIdentity = null;
|
|
310
310
|
|
|
311
311
|
// Manually generate a different phrase
|
|
312
|
-
const
|
|
313
|
-
const
|
|
312
|
+
const { generateMnemonic } = await import('@scure/bip39');
|
|
313
|
+
const { wordlist } = await import('@scure/bip39/wordlists/english');
|
|
314
|
+
const otherPhrase = generateMnemonic(wordlist, 128);
|
|
314
315
|
// Sanity check phrases are different
|
|
315
316
|
expect(otherPhrase).not.toBe(a.phrase);
|
|
316
317
|
|