@oxyhq/contracts 0.20.0 → 0.21.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/index.js +63 -4
- package/dist/cjs/moderationReputation.js +298 -0
- package/dist/cjs/reputation.js +15 -3
- package/dist/cjs/userInvalidation.js +89 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/index.js +12 -0
- package/dist/esm/moderationReputation.js +295 -0
- package/dist/esm/reputation.js +15 -3
- package/dist/esm/userInvalidation.js +85 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +4 -0
- package/dist/types/moderationReputation.d.ts +487 -0
- package/dist/types/reputation.d.ts +16 -0
- package/dist/types/userInvalidation.d.ts +94 -0
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -11,10 +11,11 @@
|
|
|
11
11
|
* expo, no `require()` in the ESM build.
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.
|
|
15
|
-
exports.
|
|
16
|
-
exports.
|
|
17
|
-
exports.
|
|
14
|
+
exports.exportAttestationSchema = exports.authMethodsResponseSchema = exports.authMethodEntrySchema = exports.domainVerificationInstructionsSchema = exports.domainVerificationRequestSchema = exports.verifiedDomainSchema = exports.signedRecordEnvelopeSchema = exports.didDocumentSchema = exports.didServiceSchema = exports.verificationMethodSchema = exports.appAffinityEventsIngestSchema = exports.appAffinityEventSchema = exports.appAffinityEventTypeSchema = exports.appUserSignalIngestSchema = exports.appInterestInputSchema = exports.appEndorsementInputSchema = exports.recommendationResponseSchema = exports.recommendationItemSchema = exports.recommendationCountSchema = exports.recommendationRequestSchema = exports.recommendationSignalWeightsSchema = exports.recommendationBoostSchema = exports.recommendationExcludeTypeSchema = exports.oxyUserInvalidationEventSchema = exports.isPublishedOxyUserChangeReason = exports.OXY_PUBLISHED_USER_CHANGE_REASONS = exports.OXY_USER_CHANGE_REASONS = exports.OXY_USER_INVALIDATION_CHANNEL = exports.inboxEmailPushDataSchema = exports.INBOX_EMAIL_PUSH_TYPE = exports.INBOX_EMAIL_PUSH_CHANNEL = exports.IDENTITY_APPROVAL_PUSH_CHANNEL = exports.commonsDenyReasonSchema = exports.COMMONS_DENY_REASONS = exports.sessionStatusSchema = exports.publicApplicationSchema = exports.applicationTypeSchema = exports.safeParseContract = exports.resolveUserId = exports.deviceLinkedSessionsResponseSchema = exports.deviceLinkedSessionSchema = exports.currentUserResponseSchema = exports.userProfileUpdateSchema = exports.userResponseSchema = exports.themePreferenceSchema = exports.userRelationshipSchema = exports.userNameSchema = exports.createAccountRequestSchema = exports.organizationCategorySchema = exports.ORGANIZATION_CATEGORIES = void 0;
|
|
15
|
+
exports.upsertReputationRuleSchema = exports.resolveReputationDisputeSchema = exports.createReputationDisputeSchema = exports.awardReputationSchema = exports.reverseReputationTransactionResultSchema = exports.reputationInfluenceResultSchema = exports.reputationLeaderboardEntrySchema = exports.reputationLeaderboardUserSchema = exports.reputationRuleSchema = exports.reputationDisputeSchema = exports.reputationBalanceSchema = exports.reputationBalanceSummarySchema = exports.reputationReliabilitySchema = exports.reputationInfluenceSchema = exports.reputationBalanceBreakdownSchema = exports.reputationTransactionSchema = exports.reputationInfluenceContextSchema = exports.reputationDisputeStatusSchema = exports.reputationTargetEntityTypeSchema = exports.trustTierSchema = exports.reputationTransactionStatusSchema = exports.reputationCategorySchema = exports.REPUTATION_INFLUENCE_CONTEXTS = exports.REPUTATION_DISPUTE_STATUSES = exports.REPUTATION_TARGET_ENTITY_TYPES = exports.TRUST_TIERS = exports.REPUTATION_TRANSACTION_STATUSES = exports.REPUTATION_CATEGORIES = exports.credentialVerifyResultSchema = exports.credentialListResultSchema = exports.credentialIssueResultSchema = exports.verifiableCredentialResponseSchema = exports.credentialRecordSchema = exports.vouchResultSchema = exports.personhoodStatusResultSchema = exports.personhoodBreakdownSchema = exports.personhoodVouchRecordSchema = exports.validationVoteResultSchema = exports.validationRequestSummarySchema = exports.validationOpenResultSchema = exports.validationOpenRequestSchema = exports.validationVerdictRecordSchema = exports.realLifeAttestationResultSchema = exports.realLifeAttestationRecordSchema = exports.signedPublicCardSchema = exports.publicCardSchema = exports.logPageResponseSchema = exports.chainHeadResponseSchema = exports.oxySignedRecordTypeSchema = exports.exportBundleSchema = void 0;
|
|
16
|
+
exports.linkPreviewBatchRequestSchema = exports.linkPreviewSchema = exports.applicationModerationTrustSchema = exports.reputationContextualInfluenceSchema = exports.reputationReviewingSchema = exports.reputationReportingSchema = exports.reputationConductSchema = exports.reputationContributionSchema = exports.reputationPersonhoodSchema = exports.identityBindingSchema = exports.registerIdentityBindingSchema = exports.reverseModerationEffectResultSchema = exports.applyModerationDecisionResultSchema = exports.moderationEffectSchema = exports.reverseModerationEffectSchema = exports.finalizeModerationDecisionSchema = exports.moderationDecisionEventSchema = exports.moderationPolicyVersionsSchema = exports.moderationDecisionEventSubjectSchema = exports.moderationFindingSchema = exports.applicationModerationStandingSchema = exports.identityBindingStatusSchema = exports.identityBindingTypeSchema = exports.personhoodStatusSchema = exports.contributionTierSchema = exports.conductStandingSchema = exports.conductStrikeStatusSchema = exports.moderationEffectSkipReasonSchema = exports.moderationEffectStatusSchema = exports.moderationEffectTypeSchema = exports.moderationDecisionStatusSchema = exports.moderationAttributionSchema = exports.moderationFindingScopeSchema = exports.moderationSeveritySchema = exports.APPLICATION_MODERATION_STANDINGS = exports.IDENTITY_BINDING_STATUSES = exports.IDENTITY_BINDING_TYPES = exports.PERSONHOOD_STATUSES = exports.CONTRIBUTION_TIERS = exports.CONDUCT_STANDINGS = exports.CONDUCT_STRIKE_STATUSES = exports.MODERATION_EFFECT_SKIP_REASONS = exports.MODERATION_EFFECT_STATUSES = exports.MODERATION_EFFECT_TYPES = exports.MODERATION_DECISION_STATUSES = exports.MODERATION_ATTRIBUTIONS = exports.MODERATION_FINDING_SCOPES = exports.MODERATION_SEVERITIES = exports.isFullReputationBalance = exports.reverseReputationTransactionSchema = void 0;
|
|
17
|
+
exports.webauthnLoginOptionsRequestSchema = exports.webauthnRegisterOptionsRequestSchema = exports.updateRolloutPatchSchema = exports.promoteRequestSchema = exports.rollbackToEmbeddedRequestSchema = exports.rollbackRequestSchema = exports.updateListResponseSchema = exports.channelListResponseSchema = exports.channelSchema = exports.rollbackToEmbeddedEntrySchema = exports.createUpdateResponseSchema = exports.updateSchema = exports.createUpdateRequestSchema = exports.updateAssetRefSchema = exports.assetCompleteResponseSchema = exports.assetCompleteResultItemSchema = exports.assetCompleteRequestSchema = exports.assetInitResponseSchema = exports.assetUploadTicketSchema = exports.assetInitRequestSchema = exports.assetInitItemSchema = exports.rolloutPercentSchema = exports.runtimeVersionSchema = exports.channelNameSchema = exports.sha256HexSchema = exports.updateAssetStatusSchema = exports.updateStatusSchema = exports.updatePlatformSchema = exports.backupStatusResponseSchema = exports.backupUploadRequestSchema = exports.encryptedBackupEnvelopeSchema = exports.backupLookupIdSchema = exports.rotateKeyCompleteResponseSchema = exports.rotateKeyCompleteRequestSchema = exports.rotateKeyChallengeResponseSchema = exports.loginResultSchema = exports.sessionAccountsChangedEventSchema = exports.sessionAccountsChangedReasonSchema = exports.SESSION_ACCOUNTS_CHANGED_EVENT = exports.deviceBackgroundTokenResponseSchema = exports.deviceBackgroundTokenRequestSchema = exports.deviceBackgroundCredentialResponseSchema = exports.deviceTokenMintResponseSchema = exports.deviceTokenMintRequestSchema = exports.deviceSessionSyncSchema = exports.activeTokenSchema = exports.deviceSessionStateSchema = exports.sessionAccountSchema = exports.linkPreviewResponseSchema = exports.linkPreviewBatchResponseSchema = void 0;
|
|
18
|
+
exports.transparencyCheckpointListSchema = exports.transparencyInclusionProofSchema = exports.transparencyCheckpointSchema = exports.transparencyAnchorSchema = exports.transparencyCheckpointSignatureSchema = exports.deviceTransferDenyResponseSchema = exports.deviceTransferApproveResponseSchema = exports.deviceTransferApproveRequestSchema = exports.deviceTransferInfoResponseSchema = exports.deviceTransferInitResponseSchema = exports.deviceTransferInitRequestSchema = exports.devicePairingStatusSchema = exports.webauthnLoginVerifyRequestSchema = exports.webauthnRegisterVerifyRequestSchema = void 0;
|
|
18
19
|
var accountGraph_1 = require("./accountGraph");
|
|
19
20
|
Object.defineProperty(exports, "ORGANIZATION_CATEGORIES", { enumerable: true, get: function () { return accountGraph_1.ORGANIZATION_CATEGORIES; } });
|
|
20
21
|
Object.defineProperty(exports, "organizationCategorySchema", { enumerable: true, get: function () { return accountGraph_1.organizationCategorySchema; } });
|
|
@@ -48,6 +49,12 @@ var inboxPush_1 = require("./inboxPush");
|
|
|
48
49
|
Object.defineProperty(exports, "INBOX_EMAIL_PUSH_CHANNEL", { enumerable: true, get: function () { return inboxPush_1.INBOX_EMAIL_PUSH_CHANNEL; } });
|
|
49
50
|
Object.defineProperty(exports, "INBOX_EMAIL_PUSH_TYPE", { enumerable: true, get: function () { return inboxPush_1.INBOX_EMAIL_PUSH_TYPE; } });
|
|
50
51
|
Object.defineProperty(exports, "inboxEmailPushDataSchema", { enumerable: true, get: function () { return inboxPush_1.inboxEmailPushDataSchema; } });
|
|
52
|
+
var userInvalidation_1 = require("./userInvalidation");
|
|
53
|
+
Object.defineProperty(exports, "OXY_USER_INVALIDATION_CHANNEL", { enumerable: true, get: function () { return userInvalidation_1.OXY_USER_INVALIDATION_CHANNEL; } });
|
|
54
|
+
Object.defineProperty(exports, "OXY_USER_CHANGE_REASONS", { enumerable: true, get: function () { return userInvalidation_1.OXY_USER_CHANGE_REASONS; } });
|
|
55
|
+
Object.defineProperty(exports, "OXY_PUBLISHED_USER_CHANGE_REASONS", { enumerable: true, get: function () { return userInvalidation_1.OXY_PUBLISHED_USER_CHANGE_REASONS; } });
|
|
56
|
+
Object.defineProperty(exports, "isPublishedOxyUserChangeReason", { enumerable: true, get: function () { return userInvalidation_1.isPublishedOxyUserChangeReason; } });
|
|
57
|
+
Object.defineProperty(exports, "oxyUserInvalidationEventSchema", { enumerable: true, get: function () { return userInvalidation_1.oxyUserInvalidationEventSchema; } });
|
|
51
58
|
var recommendations_1 = require("./recommendations");
|
|
52
59
|
// Schemas
|
|
53
60
|
Object.defineProperty(exports, "recommendationExcludeTypeSchema", { enumerable: true, get: function () { return recommendations_1.recommendationExcludeTypeSchema; } });
|
|
@@ -142,6 +149,58 @@ Object.defineProperty(exports, "upsertReputationRuleSchema", { enumerable: true,
|
|
|
142
149
|
Object.defineProperty(exports, "reverseReputationTransactionSchema", { enumerable: true, get: function () { return reputation_1.reverseReputationTransactionSchema; } });
|
|
143
150
|
// Narrows the two balance views apart at runtime.
|
|
144
151
|
Object.defineProperty(exports, "isFullReputationBalance", { enumerable: true, get: function () { return reputation_1.isFullReputationBalance; } });
|
|
152
|
+
var moderationReputation_1 = require("./moderationReputation");
|
|
153
|
+
// Closed value sets — the moderation reputation bridge (CrowdSource → Oxy Trust).
|
|
154
|
+
Object.defineProperty(exports, "MODERATION_SEVERITIES", { enumerable: true, get: function () { return moderationReputation_1.MODERATION_SEVERITIES; } });
|
|
155
|
+
Object.defineProperty(exports, "MODERATION_FINDING_SCOPES", { enumerable: true, get: function () { return moderationReputation_1.MODERATION_FINDING_SCOPES; } });
|
|
156
|
+
Object.defineProperty(exports, "MODERATION_ATTRIBUTIONS", { enumerable: true, get: function () { return moderationReputation_1.MODERATION_ATTRIBUTIONS; } });
|
|
157
|
+
Object.defineProperty(exports, "MODERATION_DECISION_STATUSES", { enumerable: true, get: function () { return moderationReputation_1.MODERATION_DECISION_STATUSES; } });
|
|
158
|
+
Object.defineProperty(exports, "MODERATION_EFFECT_TYPES", { enumerable: true, get: function () { return moderationReputation_1.MODERATION_EFFECT_TYPES; } });
|
|
159
|
+
Object.defineProperty(exports, "MODERATION_EFFECT_STATUSES", { enumerable: true, get: function () { return moderationReputation_1.MODERATION_EFFECT_STATUSES; } });
|
|
160
|
+
Object.defineProperty(exports, "MODERATION_EFFECT_SKIP_REASONS", { enumerable: true, get: function () { return moderationReputation_1.MODERATION_EFFECT_SKIP_REASONS; } });
|
|
161
|
+
Object.defineProperty(exports, "CONDUCT_STRIKE_STATUSES", { enumerable: true, get: function () { return moderationReputation_1.CONDUCT_STRIKE_STATUSES; } });
|
|
162
|
+
Object.defineProperty(exports, "CONDUCT_STANDINGS", { enumerable: true, get: function () { return moderationReputation_1.CONDUCT_STANDINGS; } });
|
|
163
|
+
Object.defineProperty(exports, "CONTRIBUTION_TIERS", { enumerable: true, get: function () { return moderationReputation_1.CONTRIBUTION_TIERS; } });
|
|
164
|
+
Object.defineProperty(exports, "PERSONHOOD_STATUSES", { enumerable: true, get: function () { return moderationReputation_1.PERSONHOOD_STATUSES; } });
|
|
165
|
+
Object.defineProperty(exports, "IDENTITY_BINDING_TYPES", { enumerable: true, get: function () { return moderationReputation_1.IDENTITY_BINDING_TYPES; } });
|
|
166
|
+
Object.defineProperty(exports, "IDENTITY_BINDING_STATUSES", { enumerable: true, get: function () { return moderationReputation_1.IDENTITY_BINDING_STATUSES; } });
|
|
167
|
+
Object.defineProperty(exports, "APPLICATION_MODERATION_STANDINGS", { enumerable: true, get: function () { return moderationReputation_1.APPLICATION_MODERATION_STANDINGS; } });
|
|
168
|
+
// Schemas — closed value sets
|
|
169
|
+
Object.defineProperty(exports, "moderationSeveritySchema", { enumerable: true, get: function () { return moderationReputation_1.moderationSeveritySchema; } });
|
|
170
|
+
Object.defineProperty(exports, "moderationFindingScopeSchema", { enumerable: true, get: function () { return moderationReputation_1.moderationFindingScopeSchema; } });
|
|
171
|
+
Object.defineProperty(exports, "moderationAttributionSchema", { enumerable: true, get: function () { return moderationReputation_1.moderationAttributionSchema; } });
|
|
172
|
+
Object.defineProperty(exports, "moderationDecisionStatusSchema", { enumerable: true, get: function () { return moderationReputation_1.moderationDecisionStatusSchema; } });
|
|
173
|
+
Object.defineProperty(exports, "moderationEffectTypeSchema", { enumerable: true, get: function () { return moderationReputation_1.moderationEffectTypeSchema; } });
|
|
174
|
+
Object.defineProperty(exports, "moderationEffectStatusSchema", { enumerable: true, get: function () { return moderationReputation_1.moderationEffectStatusSchema; } });
|
|
175
|
+
Object.defineProperty(exports, "moderationEffectSkipReasonSchema", { enumerable: true, get: function () { return moderationReputation_1.moderationEffectSkipReasonSchema; } });
|
|
176
|
+
Object.defineProperty(exports, "conductStrikeStatusSchema", { enumerable: true, get: function () { return moderationReputation_1.conductStrikeStatusSchema; } });
|
|
177
|
+
Object.defineProperty(exports, "conductStandingSchema", { enumerable: true, get: function () { return moderationReputation_1.conductStandingSchema; } });
|
|
178
|
+
Object.defineProperty(exports, "contributionTierSchema", { enumerable: true, get: function () { return moderationReputation_1.contributionTierSchema; } });
|
|
179
|
+
Object.defineProperty(exports, "personhoodStatusSchema", { enumerable: true, get: function () { return moderationReputation_1.personhoodStatusSchema; } });
|
|
180
|
+
Object.defineProperty(exports, "identityBindingTypeSchema", { enumerable: true, get: function () { return moderationReputation_1.identityBindingTypeSchema; } });
|
|
181
|
+
Object.defineProperty(exports, "identityBindingStatusSchema", { enumerable: true, get: function () { return moderationReputation_1.identityBindingStatusSchema; } });
|
|
182
|
+
Object.defineProperty(exports, "applicationModerationStandingSchema", { enumerable: true, get: function () { return moderationReputation_1.applicationModerationStandingSchema; } });
|
|
183
|
+
// Schemas — the event and its receipt
|
|
184
|
+
Object.defineProperty(exports, "moderationFindingSchema", { enumerable: true, get: function () { return moderationReputation_1.moderationFindingSchema; } });
|
|
185
|
+
Object.defineProperty(exports, "moderationDecisionEventSubjectSchema", { enumerable: true, get: function () { return moderationReputation_1.moderationDecisionEventSubjectSchema; } });
|
|
186
|
+
Object.defineProperty(exports, "moderationPolicyVersionsSchema", { enumerable: true, get: function () { return moderationReputation_1.moderationPolicyVersionsSchema; } });
|
|
187
|
+
Object.defineProperty(exports, "moderationDecisionEventSchema", { enumerable: true, get: function () { return moderationReputation_1.moderationDecisionEventSchema; } });
|
|
188
|
+
Object.defineProperty(exports, "finalizeModerationDecisionSchema", { enumerable: true, get: function () { return moderationReputation_1.finalizeModerationDecisionSchema; } });
|
|
189
|
+
Object.defineProperty(exports, "reverseModerationEffectSchema", { enumerable: true, get: function () { return moderationReputation_1.reverseModerationEffectSchema; } });
|
|
190
|
+
Object.defineProperty(exports, "moderationEffectSchema", { enumerable: true, get: function () { return moderationReputation_1.moderationEffectSchema; } });
|
|
191
|
+
Object.defineProperty(exports, "applyModerationDecisionResultSchema", { enumerable: true, get: function () { return moderationReputation_1.applyModerationDecisionResultSchema; } });
|
|
192
|
+
Object.defineProperty(exports, "reverseModerationEffectResultSchema", { enumerable: true, get: function () { return moderationReputation_1.reverseModerationEffectResultSchema; } });
|
|
193
|
+
// Schemas — identity binding
|
|
194
|
+
Object.defineProperty(exports, "registerIdentityBindingSchema", { enumerable: true, get: function () { return moderationReputation_1.registerIdentityBindingSchema; } });
|
|
195
|
+
Object.defineProperty(exports, "identityBindingSchema", { enumerable: true, get: function () { return moderationReputation_1.identityBindingSchema; } });
|
|
196
|
+
// Schemas — the derived V2 axes
|
|
197
|
+
Object.defineProperty(exports, "reputationPersonhoodSchema", { enumerable: true, get: function () { return moderationReputation_1.reputationPersonhoodSchema; } });
|
|
198
|
+
Object.defineProperty(exports, "reputationContributionSchema", { enumerable: true, get: function () { return moderationReputation_1.reputationContributionSchema; } });
|
|
199
|
+
Object.defineProperty(exports, "reputationConductSchema", { enumerable: true, get: function () { return moderationReputation_1.reputationConductSchema; } });
|
|
200
|
+
Object.defineProperty(exports, "reputationReportingSchema", { enumerable: true, get: function () { return moderationReputation_1.reputationReportingSchema; } });
|
|
201
|
+
Object.defineProperty(exports, "reputationReviewingSchema", { enumerable: true, get: function () { return moderationReputation_1.reputationReviewingSchema; } });
|
|
202
|
+
Object.defineProperty(exports, "reputationContextualInfluenceSchema", { enumerable: true, get: function () { return moderationReputation_1.reputationContextualInfluenceSchema; } });
|
|
203
|
+
Object.defineProperty(exports, "applicationModerationTrustSchema", { enumerable: true, get: function () { return moderationReputation_1.applicationModerationTrustSchema; } });
|
|
145
204
|
var links_1 = require("./links");
|
|
146
205
|
// Schemas
|
|
147
206
|
Object.defineProperty(exports, "linkPreviewSchema", { enumerable: true, get: function () { return links_1.linkPreviewSchema; } });
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Oxy Trust — the moderation reputation bridge (CrowdSource → Oxy Trust).
|
|
4
|
+
*
|
|
5
|
+
* SINGLE SOURCE OF TRUTH for the wire shapes crossing the one-way boundary
|
|
6
|
+
* between a participatory-moderation service and the Oxy reputation ledger.
|
|
7
|
+
*
|
|
8
|
+
* The direction is not negotiable: a moderation service NEVER writes reputation.
|
|
9
|
+
* It emits an authenticated internal event describing a decision it published,
|
|
10
|
+
* and Oxy's own consequence engine validates that event and derives the effect.
|
|
11
|
+
* Everything in this module is therefore either (a) the event, (b) the receipt
|
|
12
|
+
* the engine returns, or (c) the derived state the engine publishes back to the
|
|
13
|
+
* subject.
|
|
14
|
+
*
|
|
15
|
+
* Design anchors, all load-bearing:
|
|
16
|
+
*
|
|
17
|
+
* - **Conduct is a separate axis from contribution.** A conduct penalty raises
|
|
18
|
+
* `activeRisk` and creates a strike; positive contribution points can never
|
|
19
|
+
* cancel a strike, because standing is derived from active risk and not from
|
|
20
|
+
* the point total. See {@link ReputationConduct}.
|
|
21
|
+
* - **The reporting axis carries only reporting signals.** `abuseScore` on the
|
|
22
|
+
* legacy reliability block conflated rejected reports with every negative
|
|
23
|
+
* transaction; {@link ReputationReporting} exists so a conduct penalty can
|
|
24
|
+
* never inflate a report-abuse figure.
|
|
25
|
+
* - **No binding proof, no effect.** {@link ModerationDecisionEventSubject}
|
|
26
|
+
* requires a `bindingProofId`, and the engine rejects an event whose binding
|
|
27
|
+
* does not resolve to the claimed principal at or before `occurredAt`. An
|
|
28
|
+
* application cannot move a reputation figure by naming a user id.
|
|
29
|
+
* - **One penalty per incident.** The idempotency key is
|
|
30
|
+
* `moderation:<incidentId>:<decisionRevision>:<effectType>`; a hundred
|
|
31
|
+
* reports about the same material produce one effect.
|
|
32
|
+
* - **Every effect carries the policy version it was decided under**, so a
|
|
33
|
+
* consequence can be recomputed under the original policy rather than under
|
|
34
|
+
* whatever the current tuning happens to be.
|
|
35
|
+
*
|
|
36
|
+
* Platform-agnostic — zod only. ESM-safe (no `require()`).
|
|
37
|
+
*/
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.applicationModerationTrustSchema = exports.reputationContextualInfluenceSchema = exports.reputationReviewingSchema = exports.reputationReportingSchema = exports.reputationConductSchema = exports.reputationContributionSchema = exports.reputationPersonhoodSchema = exports.identityBindingSchema = exports.registerIdentityBindingSchema = exports.reverseModerationEffectResultSchema = exports.applyModerationDecisionResultSchema = exports.moderationEffectSchema = exports.reverseModerationEffectSchema = exports.finalizeModerationDecisionSchema = exports.moderationDecisionEventSchema = exports.moderationPolicyVersionsSchema = exports.moderationDecisionEventSubjectSchema = exports.moderationFindingSchema = exports.moderationEffectSkipReasonSchema = exports.MODERATION_EFFECT_SKIP_REASONS = exports.applicationModerationStandingSchema = exports.APPLICATION_MODERATION_STANDINGS = exports.identityBindingStatusSchema = exports.IDENTITY_BINDING_STATUSES = exports.identityBindingTypeSchema = exports.IDENTITY_BINDING_TYPES = exports.personhoodStatusSchema = exports.PERSONHOOD_STATUSES = exports.contributionTierSchema = exports.CONTRIBUTION_TIERS = exports.conductStandingSchema = exports.CONDUCT_STANDINGS = exports.conductStrikeStatusSchema = exports.CONDUCT_STRIKE_STATUSES = exports.moderationEffectStatusSchema = exports.MODERATION_EFFECT_STATUSES = exports.moderationEffectTypeSchema = exports.MODERATION_EFFECT_TYPES = exports.moderationDecisionStatusSchema = exports.MODERATION_DECISION_STATUSES = exports.moderationAttributionSchema = exports.MODERATION_ATTRIBUTIONS = exports.moderationFindingScopeSchema = exports.MODERATION_FINDING_SCOPES = exports.moderationSeveritySchema = exports.MODERATION_SEVERITIES = void 0;
|
|
40
|
+
const zod_1 = require("zod");
|
|
41
|
+
/* -------------------------------------------------------------------------- */
|
|
42
|
+
/* Closed value sets */
|
|
43
|
+
/* -------------------------------------------------------------------------- */
|
|
44
|
+
/**
|
|
45
|
+
* Severity band of a moderation finding, lowest → highest.
|
|
46
|
+
*
|
|
47
|
+
* The band — not the taxonomy code — is what the consequence engine consumes:
|
|
48
|
+
* points, active risk and expiry are all keyed by severity in the versioned
|
|
49
|
+
* conduct policy, so a new taxonomy code needs no engine change and no
|
|
50
|
+
* intimate category ever reaches the ledger.
|
|
51
|
+
*/
|
|
52
|
+
exports.MODERATION_SEVERITIES = ['low', 'medium', 'high', 'critical'];
|
|
53
|
+
exports.moderationSeveritySchema = zod_1.z.enum(exports.MODERATION_SEVERITIES);
|
|
54
|
+
/**
|
|
55
|
+
* How far a finding reaches.
|
|
56
|
+
*
|
|
57
|
+
* - `application_local` — the application enforces locally; Oxy Trust is NOT
|
|
58
|
+
* touched. Emitted for completeness; the engine rejects the effect.
|
|
59
|
+
* - `oxy_network` — conduct against the Oxy network as a whole.
|
|
60
|
+
* - `identity_integrity` — impersonation, sybil behaviour, credential abuse.
|
|
61
|
+
*
|
|
62
|
+
* Only `oxy_network` and `identity_integrity` can produce a global effect.
|
|
63
|
+
*/
|
|
64
|
+
exports.MODERATION_FINDING_SCOPES = [
|
|
65
|
+
'application_local',
|
|
66
|
+
'oxy_network',
|
|
67
|
+
'identity_integrity',
|
|
68
|
+
];
|
|
69
|
+
exports.moderationFindingScopeSchema = zod_1.z.enum(exports.MODERATION_FINDING_SCOPES);
|
|
70
|
+
/** Which participant in the reported material the finding attributes to. */
|
|
71
|
+
exports.MODERATION_ATTRIBUTIONS = ['author', 'sharer', 'reporter', 'reviewer'];
|
|
72
|
+
exports.moderationAttributionSchema = zod_1.z.enum(exports.MODERATION_ATTRIBUTIONS);
|
|
73
|
+
/**
|
|
74
|
+
* Lifecycle of the decision the event describes.
|
|
75
|
+
*
|
|
76
|
+
* `inconclusive` is its own outcome and never collapses into "no violation";
|
|
77
|
+
* it simply produces no effect. `superseded` and `corrected` describe a
|
|
78
|
+
* revision that a later one replaced — an event in either state is rejected,
|
|
79
|
+
* because applying it would resurrect a consequence the appeal removed.
|
|
80
|
+
*/
|
|
81
|
+
exports.MODERATION_DECISION_STATUSES = [
|
|
82
|
+
'provisional',
|
|
83
|
+
'final',
|
|
84
|
+
'inconclusive',
|
|
85
|
+
'superseded',
|
|
86
|
+
'corrected',
|
|
87
|
+
];
|
|
88
|
+
exports.moderationDecisionStatusSchema = zod_1.z.enum(exports.MODERATION_DECISION_STATUSES);
|
|
89
|
+
/**
|
|
90
|
+
* The kind of consequence an effect carries. Each is its own axis, and the
|
|
91
|
+
* idempotency key includes it — one incident may legitimately produce a conduct
|
|
92
|
+
* effect for the author AND a report-abuse effect for a malicious reporter.
|
|
93
|
+
*/
|
|
94
|
+
exports.MODERATION_EFFECT_TYPES = [
|
|
95
|
+
'conduct_penalty',
|
|
96
|
+
'report_abuse_penalty',
|
|
97
|
+
'review_abuse_penalty',
|
|
98
|
+
];
|
|
99
|
+
exports.moderationEffectTypeSchema = zod_1.z.enum(exports.MODERATION_EFFECT_TYPES);
|
|
100
|
+
/** Lifecycle of a stored effect. */
|
|
101
|
+
exports.MODERATION_EFFECT_STATUSES = ['applied', 'reversed'];
|
|
102
|
+
exports.moderationEffectStatusSchema = zod_1.z.enum(exports.MODERATION_EFFECT_STATUSES);
|
|
103
|
+
/** Lifecycle of a conduct strike. Only `active` strikes carry active risk. */
|
|
104
|
+
exports.CONDUCT_STRIKE_STATUSES = ['active', 'expired', 'reversed'];
|
|
105
|
+
exports.conductStrikeStatusSchema = zod_1.z.enum(exports.CONDUCT_STRIKE_STATUSES);
|
|
106
|
+
/**
|
|
107
|
+
* Conduct standing, derived from ACTIVE RISK and nothing else.
|
|
108
|
+
*
|
|
109
|
+
* Deliberately independent of the point total: a person may hold a high
|
|
110
|
+
* contribution tier and a `limited` standing at the same time, and earning
|
|
111
|
+
* points cannot move standing back toward `good`. Only expiry or reversal can.
|
|
112
|
+
*/
|
|
113
|
+
exports.CONDUCT_STANDINGS = ['good', 'watch', 'limited', 'restricted'];
|
|
114
|
+
exports.conductStandingSchema = zod_1.z.enum(exports.CONDUCT_STANDINGS);
|
|
115
|
+
/** Contribution tier, derived from contribution points only. */
|
|
116
|
+
exports.CONTRIBUTION_TIERS = ['new', 'trusted', 'high_trust'];
|
|
117
|
+
exports.contributionTierSchema = zod_1.z.enum(exports.CONTRIBUTION_TIERS);
|
|
118
|
+
/** Personhood status. Being a real person proves neither conduct nor competence. */
|
|
119
|
+
exports.PERSONHOOD_STATUSES = ['unknown', 'probable', 'verified'];
|
|
120
|
+
exports.personhoodStatusSchema = zod_1.z.enum(exports.PERSONHOOD_STATUSES);
|
|
121
|
+
/**
|
|
122
|
+
* How an Oxy identity was bound to the actor an application reported.
|
|
123
|
+
*
|
|
124
|
+
* - `oauth_grant` — the user authorized the application through Oxy's own
|
|
125
|
+
* OAuth flow. Oxy wrote the record; the application asserts nothing.
|
|
126
|
+
* - `session_proof` — the application presented the USER'S OWN Oxy access
|
|
127
|
+
* token alongside its service credential, proving the user was present in
|
|
128
|
+
* that application under a named local principal id.
|
|
129
|
+
* - `commons_signature` — a DID-verifiable signature over a server-issued nonce.
|
|
130
|
+
* - `federated_actor` — a resolvable, authorized federated actor link.
|
|
131
|
+
*/
|
|
132
|
+
exports.IDENTITY_BINDING_TYPES = [
|
|
133
|
+
'oauth_grant',
|
|
134
|
+
'session_proof',
|
|
135
|
+
'commons_signature',
|
|
136
|
+
'federated_actor',
|
|
137
|
+
];
|
|
138
|
+
exports.identityBindingTypeSchema = zod_1.z.enum(exports.IDENTITY_BINDING_TYPES);
|
|
139
|
+
/** Binding lifecycle. A revoked binding proves nothing about a later action. */
|
|
140
|
+
exports.IDENTITY_BINDING_STATUSES = ['active', 'revoked'];
|
|
141
|
+
exports.identityBindingStatusSchema = zod_1.z.enum(exports.IDENTITY_BINDING_STATUSES);
|
|
142
|
+
/**
|
|
143
|
+
* An application's own moderation standing. An external application can abuse
|
|
144
|
+
* the system too, so it carries standing exactly like a person does.
|
|
145
|
+
*
|
|
146
|
+
* `sandbox` applications moderate locally and produce NO global effect.
|
|
147
|
+
*/
|
|
148
|
+
exports.APPLICATION_MODERATION_STANDINGS = ['sandbox', 'trusted', 'restricted'];
|
|
149
|
+
exports.applicationModerationStandingSchema = zod_1.z.enum(exports.APPLICATION_MODERATION_STANDINGS);
|
|
150
|
+
/**
|
|
151
|
+
* Why the engine declined to apply an effect.
|
|
152
|
+
*
|
|
153
|
+
* Returned rather than thrown for the cases that are a legitimate outcome of a
|
|
154
|
+
* well-formed event (a sandboxed application, a local-only finding, an
|
|
155
|
+
* inconclusive decision): the emitter must be able to record "delivered, no
|
|
156
|
+
* effect" and stop retrying. Malformed or unauthorized events are HTTP errors,
|
|
157
|
+
* not skip reasons.
|
|
158
|
+
*/
|
|
159
|
+
exports.MODERATION_EFFECT_SKIP_REASONS = [
|
|
160
|
+
'no_binding_proof',
|
|
161
|
+
'binding_after_action',
|
|
162
|
+
'binding_principal_mismatch',
|
|
163
|
+
'binding_revoked',
|
|
164
|
+
'decision_not_effective',
|
|
165
|
+
'decision_superseded',
|
|
166
|
+
'finding_scope_local',
|
|
167
|
+
'finding_not_in_policy',
|
|
168
|
+
'application_not_permitted',
|
|
169
|
+
'no_effective_finding',
|
|
170
|
+
];
|
|
171
|
+
exports.moderationEffectSkipReasonSchema = zod_1.z.enum(exports.MODERATION_EFFECT_SKIP_REASONS);
|
|
172
|
+
exports.moderationFindingSchema = zod_1.z.object({
|
|
173
|
+
code: zod_1.z.string().trim().min(1).max(200),
|
|
174
|
+
severity: exports.moderationSeveritySchema,
|
|
175
|
+
scope: exports.moderationFindingScopeSchema,
|
|
176
|
+
attribution: exports.moderationAttributionSchema,
|
|
177
|
+
family: zod_1.z.string().trim().min(1).max(100),
|
|
178
|
+
});
|
|
179
|
+
exports.moderationDecisionEventSubjectSchema = zod_1.z.object({
|
|
180
|
+
principalType: zod_1.z.literal('oxy_user'),
|
|
181
|
+
principalId: zod_1.z.string().trim().min(1),
|
|
182
|
+
bindingProofId: zod_1.z.string().trim().min(1),
|
|
183
|
+
});
|
|
184
|
+
exports.moderationPolicyVersionsSchema = zod_1.z.object({
|
|
185
|
+
universal: zod_1.z.string().trim().min(1).max(100),
|
|
186
|
+
application: zod_1.z.string().trim().min(1).max(100),
|
|
187
|
+
oxyConduct: zod_1.z.string().trim().min(1).max(100),
|
|
188
|
+
});
|
|
189
|
+
exports.moderationDecisionEventSchema = zod_1.z.object({
|
|
190
|
+
eventId: zod_1.z.string().trim().min(1).max(200),
|
|
191
|
+
reportedApplicationId: zod_1.z.string().trim().min(1).max(200),
|
|
192
|
+
type: zod_1.z.string().trim().min(1).max(200),
|
|
193
|
+
caseId: zod_1.z.string().trim().min(1).max(200),
|
|
194
|
+
incidentId: zod_1.z.string().trim().min(1).max(200),
|
|
195
|
+
decisionId: zod_1.z.string().trim().min(1).max(200),
|
|
196
|
+
decisionRevision: zod_1.z.number().int().min(1),
|
|
197
|
+
subject: exports.moderationDecisionEventSubjectSchema,
|
|
198
|
+
findings: zod_1.z.array(exports.moderationFindingSchema).min(1).max(20),
|
|
199
|
+
decisionStatus: exports.moderationDecisionStatusSchema,
|
|
200
|
+
policyVersions: exports.moderationPolicyVersionsSchema,
|
|
201
|
+
occurredAt: zod_1.z.string().trim().min(1),
|
|
202
|
+
proofHash: zod_1.z.string().trim().min(1).max(200),
|
|
203
|
+
});
|
|
204
|
+
exports.finalizeModerationDecisionSchema = zod_1.z.object({
|
|
205
|
+
decisionId: zod_1.z.string().trim().min(1).max(200),
|
|
206
|
+
decisionRevision: zod_1.z.number().int().min(1),
|
|
207
|
+
});
|
|
208
|
+
exports.reverseModerationEffectSchema = zod_1.z.object({
|
|
209
|
+
decisionId: zod_1.z.string().trim().min(1).max(200),
|
|
210
|
+
decisionRevision: zod_1.z.number().int().min(1),
|
|
211
|
+
reason: zod_1.z.string().trim().min(1).max(500),
|
|
212
|
+
});
|
|
213
|
+
exports.moderationEffectSchema = zod_1.z.object({
|
|
214
|
+
id: zod_1.z.string(),
|
|
215
|
+
incidentId: zod_1.z.string(),
|
|
216
|
+
caseId: zod_1.z.string(),
|
|
217
|
+
decisionId: zod_1.z.string(),
|
|
218
|
+
decisionRevision: zod_1.z.number(),
|
|
219
|
+
principalId: zod_1.z.string(),
|
|
220
|
+
effectType: exports.moderationEffectTypeSchema,
|
|
221
|
+
status: exports.moderationEffectStatusSchema,
|
|
222
|
+
points: zod_1.z.number(),
|
|
223
|
+
activeRisk: zod_1.z.number(),
|
|
224
|
+
severity: exports.moderationSeveritySchema,
|
|
225
|
+
repetitionMultiplier: zod_1.z.number(),
|
|
226
|
+
multiFindingMultiplier: zod_1.z.number(),
|
|
227
|
+
idempotencyKey: zod_1.z.string(),
|
|
228
|
+
transactionId: zod_1.z.string(),
|
|
229
|
+
strikeId: zod_1.z.string().optional(),
|
|
230
|
+
reversalTransactionId: zod_1.z.string().optional(),
|
|
231
|
+
policyVersions: exports.moderationPolicyVersionsSchema,
|
|
232
|
+
appliedAt: zod_1.z.string(),
|
|
233
|
+
reversedAt: zod_1.z.string().optional(),
|
|
234
|
+
});
|
|
235
|
+
exports.applyModerationDecisionResultSchema = zod_1.z.object({
|
|
236
|
+
applied: zod_1.z.boolean(),
|
|
237
|
+
effect: exports.moderationEffectSchema.optional(),
|
|
238
|
+
skipReason: exports.moderationEffectSkipReasonSchema.optional(),
|
|
239
|
+
idempotent: zod_1.z.boolean(),
|
|
240
|
+
});
|
|
241
|
+
exports.reverseModerationEffectResultSchema = zod_1.z.object({
|
|
242
|
+
reversed: zod_1.z.array(exports.moderationEffectSchema),
|
|
243
|
+
idempotent: zod_1.z.boolean(),
|
|
244
|
+
});
|
|
245
|
+
exports.registerIdentityBindingSchema = zod_1.z.object({
|
|
246
|
+
localPrincipalId: zod_1.z.string().trim().min(1).max(200),
|
|
247
|
+
userProofToken: zod_1.z.string().trim().min(1),
|
|
248
|
+
});
|
|
249
|
+
exports.identityBindingSchema = zod_1.z.object({
|
|
250
|
+
id: zod_1.z.string(),
|
|
251
|
+
applicationId: zod_1.z.string(),
|
|
252
|
+
userId: zod_1.z.string(),
|
|
253
|
+
localPrincipalId: zod_1.z.string(),
|
|
254
|
+
bindingType: exports.identityBindingTypeSchema,
|
|
255
|
+
status: exports.identityBindingStatusSchema,
|
|
256
|
+
verifiedAt: zod_1.z.string(),
|
|
257
|
+
createdAt: zod_1.z.string(),
|
|
258
|
+
});
|
|
259
|
+
exports.reputationPersonhoodSchema = zod_1.z.object({
|
|
260
|
+
status: exports.personhoodStatusSchema,
|
|
261
|
+
score: zod_1.z.number(),
|
|
262
|
+
});
|
|
263
|
+
exports.reputationContributionSchema = zod_1.z.object({
|
|
264
|
+
points: zod_1.z.number(),
|
|
265
|
+
tier: exports.contributionTierSchema,
|
|
266
|
+
});
|
|
267
|
+
exports.reputationConductSchema = zod_1.z.object({
|
|
268
|
+
standing: exports.conductStandingSchema,
|
|
269
|
+
activeRisk: zod_1.z.number(),
|
|
270
|
+
activeStrikes: zod_1.z.number(),
|
|
271
|
+
nextExpiryAt: zod_1.z.string().optional(),
|
|
272
|
+
});
|
|
273
|
+
exports.reputationReportingSchema = zod_1.z.object({
|
|
274
|
+
reliability: zod_1.z.number(),
|
|
275
|
+
confidence: zod_1.z.number(),
|
|
276
|
+
confirmed: zod_1.z.number(),
|
|
277
|
+
rejected: zod_1.z.number(),
|
|
278
|
+
malicious: zod_1.z.number(),
|
|
279
|
+
});
|
|
280
|
+
exports.reputationReviewingSchema = zod_1.z.object({
|
|
281
|
+
globalReliability: zod_1.z.number(),
|
|
282
|
+
categoryReliability: zod_1.z.record(zod_1.z.number()),
|
|
283
|
+
languageReliability: zod_1.z.record(zod_1.z.number()),
|
|
284
|
+
});
|
|
285
|
+
exports.reputationContextualInfluenceSchema = zod_1.z.object({
|
|
286
|
+
reportPriorityWeight: zod_1.z.number(),
|
|
287
|
+
reviewSelectionWeight: zod_1.z.number(),
|
|
288
|
+
rankingWeight: zod_1.z.number(),
|
|
289
|
+
});
|
|
290
|
+
exports.applicationModerationTrustSchema = zod_1.z.object({
|
|
291
|
+
applicationId: zod_1.z.string(),
|
|
292
|
+
standing: exports.applicationModerationStandingSchema,
|
|
293
|
+
evidenceIntegrity: zod_1.z.number(),
|
|
294
|
+
identityBindingReliability: zod_1.z.number(),
|
|
295
|
+
decisionOverturnRate: zod_1.z.number(),
|
|
296
|
+
policyQuality: zod_1.z.number(),
|
|
297
|
+
globalReputationEffectsAllowed: zod_1.z.boolean(),
|
|
298
|
+
});
|
package/dist/cjs/reputation.js
CHANGED
|
@@ -45,6 +45,7 @@ exports.reverseReputationTransactionSchema = exports.upsertReputationRuleSchema
|
|
|
45
45
|
exports.isFullReputationBalance = isFullReputationBalance;
|
|
46
46
|
const zod_1 = require("zod");
|
|
47
47
|
const userResponse_1 = require("./userResponse");
|
|
48
|
+
const moderationReputation_1 = require("./moderationReputation");
|
|
48
49
|
/* -------------------------------------------------------------------------- */
|
|
49
50
|
/* Closed value sets */
|
|
50
51
|
/* -------------------------------------------------------------------------- */
|
|
@@ -181,11 +182,22 @@ exports.reputationBalanceSchema = zod_1.z.object({
|
|
|
181
182
|
reliability: exports.reputationReliabilitySchema,
|
|
182
183
|
recalculatedAt: zod_1.z.string(),
|
|
183
184
|
updatedAt: zod_1.z.string(),
|
|
185
|
+
personhood: moderationReputation_1.reputationPersonhoodSchema.optional(),
|
|
186
|
+
contribution: moderationReputation_1.reputationContributionSchema.optional(),
|
|
187
|
+
conduct: moderationReputation_1.reputationConductSchema.optional(),
|
|
188
|
+
reporting: moderationReputation_1.reputationReportingSchema.optional(),
|
|
189
|
+
reviewing: moderationReputation_1.reputationReviewingSchema.optional(),
|
|
190
|
+
contextualInfluence: moderationReputation_1.reputationContextualInfluenceSchema.optional(),
|
|
184
191
|
});
|
|
185
192
|
/**
|
|
186
|
-
*
|
|
187
|
-
* {@link ReputationBalanceSummary}
|
|
188
|
-
*
|
|
193
|
+
* The fields the full {@link ReputationBalance} carries beyond the public
|
|
194
|
+
* {@link ReputationBalanceSummary} that the API sends ALL-OR-NOTHING. The
|
|
195
|
+
* runtime discriminant between the two views.
|
|
196
|
+
*
|
|
197
|
+
* The V2 blocks (`conduct`, `contribution`, …) are deliberately NOT listed:
|
|
198
|
+
* they are optional on the wire, so requiring them here would make a balance
|
|
199
|
+
* from a server that predates them fail to narrow, hiding the whole private
|
|
200
|
+
* view. Read a V2 block by checking that block.
|
|
189
201
|
*/
|
|
190
202
|
const FULL_BALANCE_FIELDS = [
|
|
191
203
|
'positive',
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Canonical contract for the Oxy user-invalidation broadcast.
|
|
4
|
+
*
|
|
5
|
+
* Oxy owns identity, but consumers cache it: Mention keeps a Redis summary per
|
|
6
|
+
* post author, and every backend using `@oxyhq/core` holds the SDK's own GET
|
|
7
|
+
* response cache. Both go stale the moment a profile is edited, and neither has
|
|
8
|
+
* any way to find out — the writer is a different process in a different repo.
|
|
9
|
+
* This is the signal that tells them.
|
|
10
|
+
*
|
|
11
|
+
* The channel name and the payload shape are wire contracts between oxy-api (the
|
|
12
|
+
* publisher) and every consuming backend (the subscribers), so they live here
|
|
13
|
+
* rather than in either side. A hand-typed copy of the channel name fails as
|
|
14
|
+
* "the invalidation never arrives" — silently, because pub/sub has no delivery
|
|
15
|
+
* receipt and a message nobody is listening for is indistinguishable from a
|
|
16
|
+
* message nobody sent.
|
|
17
|
+
*
|
|
18
|
+
* DELIVERY IS AT-MOST-ONCE, AND THAT IS THE DESIGN. Every consumer's cache still
|
|
19
|
+
* carries its own TTL, so a dropped message degrades to exactly the behaviour
|
|
20
|
+
* before this signal existed and never to something worse. That property is what
|
|
21
|
+
* makes a bare Redis PUBLISH sufficient here and an outbox, retries, delivery
|
|
22
|
+
* receipts and payload signatures unnecessary. Do not treat a received event as
|
|
23
|
+
* authoritative for anything except "re-read this user from Oxy".
|
|
24
|
+
*
|
|
25
|
+
* PRIVACY — the payload carries NO user data, only an id, a reason and a
|
|
26
|
+
* timestamp. The channel rides the shared Valkey that every Oxy backend can
|
|
27
|
+
* subscribe to, so anything placed on it is readable by every service in the
|
|
28
|
+
* ecosystem. Never add a name, handle, email, avatar or any profile field: a
|
|
29
|
+
* subscriber that wants the new values re-reads them from Oxy through its normal
|
|
30
|
+
* authenticated path, where the usual authorization applies.
|
|
31
|
+
*
|
|
32
|
+
* Platform-agnostic — zod only, no react/react-native/expo.
|
|
33
|
+
*/
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.oxyUserInvalidationEventSchema = exports.OXY_PUBLISHED_USER_CHANGE_REASONS = exports.OXY_USER_CHANGE_REASONS = exports.OXY_USER_INVALIDATION_CHANNEL = void 0;
|
|
36
|
+
exports.isPublishedOxyUserChangeReason = isPublishedOxyUserChangeReason;
|
|
37
|
+
const zod_1 = require("zod");
|
|
38
|
+
/** Redis pub/sub channel carrying user-invalidation events. */
|
|
39
|
+
exports.OXY_USER_INVALIDATION_CHANNEL = 'oxy:user:invalidate';
|
|
40
|
+
/**
|
|
41
|
+
* Why a user record changed, as classified by the writer in oxy-api.
|
|
42
|
+
*
|
|
43
|
+
* - `profile` — anything a consumer renders or caches as IDENTITY: display name,
|
|
44
|
+
* username, avatar, bio, verification, federation fields, account status. This
|
|
45
|
+
* is the DEFAULT for every writer, so a site that forgets to classify itself
|
|
46
|
+
* over-invalidates (correct, marginally slower) rather than under-invalidates
|
|
47
|
+
* (silently wrong). Keep that asymmetry if you add a reason.
|
|
48
|
+
* - `graph` — follow-edge churn only (follower/following counts). High frequency,
|
|
49
|
+
* and bulk follow/unfollow moves up to 200 edges in one call. Nothing renders
|
|
50
|
+
* identity from it and a stale count is harmless to ranking, so it is NOT
|
|
51
|
+
* broadcast — see {@link OXY_PUBLISHED_USER_CHANGE_REASONS}.
|
|
52
|
+
*/
|
|
53
|
+
exports.OXY_USER_CHANGE_REASONS = ['profile', 'graph'];
|
|
54
|
+
/**
|
|
55
|
+
* The reasons that are actually put on the wire.
|
|
56
|
+
*
|
|
57
|
+
* A reason absent from this list is a local cache eviction in oxy-api and
|
|
58
|
+
* nothing more: no message is published at all, rather than a message every
|
|
59
|
+
* subscriber receives and discards. The distinction matters at bulk-follow
|
|
60
|
+
* scale, where the discarded variant is a 200-message burst on a channel every
|
|
61
|
+
* Oxy backend is subscribed to.
|
|
62
|
+
*
|
|
63
|
+
* This is deliberately a shared list rather than a check inside the publisher:
|
|
64
|
+
* a subscriber needs to know what it can receive, and the schema below rejects
|
|
65
|
+
* anything else, so publisher and subscriber cannot drift into disagreeing about
|
|
66
|
+
* which events exist. Adding a reason therefore forces an explicit decision about
|
|
67
|
+
* whether it broadcasts.
|
|
68
|
+
*/
|
|
69
|
+
exports.OXY_PUBLISHED_USER_CHANGE_REASONS = ['profile'];
|
|
70
|
+
/** Whether a change of this kind is broadcast to consumers at all. */
|
|
71
|
+
function isPublishedOxyUserChangeReason(reason) {
|
|
72
|
+
return exports.OXY_PUBLISHED_USER_CHANGE_REASONS.includes(reason);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* A single user-invalidation event.
|
|
76
|
+
*
|
|
77
|
+
* `at` is the publisher's epoch-ms clock, carried for diagnosis (measuring
|
|
78
|
+
* end-to-end propagation, spotting a wedged subscriber) — never for ordering or
|
|
79
|
+
* conflict resolution. Two Oxy tasks publish from unsynchronised clocks, and the
|
|
80
|
+
* event says only "re-read this user", which is idempotent and order-independent.
|
|
81
|
+
*/
|
|
82
|
+
exports.oxyUserInvalidationEventSchema = zod_1.z.object({
|
|
83
|
+
/** The Oxy user whose record changed. */
|
|
84
|
+
userId: zod_1.z.string().min(1),
|
|
85
|
+
/** Why it changed. Only broadcast reasons appear on the wire. */
|
|
86
|
+
reason: zod_1.z.enum(exports.OXY_PUBLISHED_USER_CHANGE_REASONS),
|
|
87
|
+
/** Publisher's epoch-ms timestamp. Diagnostic only. */
|
|
88
|
+
at: zod_1.z.number().int().nonnegative(),
|
|
89
|
+
});
|