@oxy.so/contracts 4.21.0 → 4.22.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.
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ /**
3
+ * Content claims (ADR 0043 D10) — the constants of the public "Report content
4
+ * / rights claim" intake and of a claim's review, without Zod. Schemas:
5
+ * `../contentClaims.ts`.
6
+ *
7
+ * Part of `@oxy.so/contracts/client`: never import `zod` here (see `./check.ts`).
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.COUNTER_NOTICE_STATEMENT_VERSION = exports.COUNTER_NOTICE_STATEMENTS = exports.CONTENT_CLAIM_COUNTER_NOTICE_LIMITS = exports.CONTENT_CLAIM_REFERENCE_PATTERN = exports.CONTENT_CLAIM_ERROR_CODES = exports.ERASURE_REQUEST_DEADLINE_DAYS = exports.CLOSED_CONTENT_CLAIM_STATES = exports.OPEN_CONTENT_CLAIM_STATES = exports.CONTENT_CLAIM_STATES = exports.CONTENT_CLAIM_LIMITS = exports.CLAIMANT_RELATIONSHIPS = exports.CONTENT_CLAIM_KINDS = void 0;
11
+ exports.isRightsClaim = isRightsClaim;
12
+ exports.isErasureRequest = isErasureRequest;
13
+ /** What a claim asserts. */
14
+ exports.CONTENT_CLAIM_KINDS = [
15
+ 'copyright',
16
+ 'trademark',
17
+ 'privacy',
18
+ 'illegal_content',
19
+ 'other',
20
+ ];
21
+ /** Who the claimant is to the content. */
22
+ exports.CLAIMANT_RELATIONSHIPS = [
23
+ 'rights_holder',
24
+ 'authorized_agent',
25
+ 'affected_person',
26
+ 'other',
27
+ ];
28
+ /** The bounds of a submission. The website fills its validation messages from these. */
29
+ exports.CONTENT_CLAIM_LIMITS = {
30
+ minUrls: 1,
31
+ maxUrls: 20,
32
+ maxUrlLength: 2048,
33
+ minDescription: 20,
34
+ maxDescription: 5000,
35
+ maxName: 200,
36
+ maxOrganization: 200,
37
+ maxEmail: 254,
38
+ };
39
+ /**
40
+ * Where a claim is in its review.
41
+ *
42
+ * `received → reviewing → actioned | rejected`; an actioned claim can be
43
+ * answered by the content's owner (`counter_noticed`), which ends either in
44
+ * `reinstated` (the content is served again) or `upheld` (it stays blocked).
45
+ * A claim can also be rejected straight from `received`.
46
+ */
47
+ exports.CONTENT_CLAIM_STATES = [
48
+ 'received',
49
+ 'reviewing',
50
+ 'actioned',
51
+ 'rejected',
52
+ 'counter_noticed',
53
+ 'reinstated',
54
+ 'upheld',
55
+ ];
56
+ /** The states in which a claim is still open: its evidence is kept and its blocks can change. */
57
+ exports.OPEN_CONTENT_CLAIM_STATES = [
58
+ 'received',
59
+ 'reviewing',
60
+ 'actioned',
61
+ 'counter_noticed',
62
+ ];
63
+ /** The states a claim ends in. */
64
+ exports.CLOSED_CONTENT_CLAIM_STATES = [
65
+ 'rejected',
66
+ 'reinstated',
67
+ 'upheld',
68
+ ];
69
+ /**
70
+ * The kinds whose claimant asserts a right in a work or a mark. Only these
71
+ * carry the link to the original — a privacy or illegal-content report
72
+ * asserts no ownership.
73
+ */
74
+ function isRightsClaim(kind) {
75
+ return kind === 'copyright' || kind === 'trademark';
76
+ }
77
+ /**
78
+ * A request to erase the claimant's OWN personal data (GDPR art. 17): a
79
+ * privacy claim made by the person it is about. Oxy must answer it within one
80
+ * month (art. 12(3)); the claim carries that deadline.
81
+ */
82
+ function isErasureRequest(kind, relationship) {
83
+ return kind === 'privacy' && relationship === 'affected_person';
84
+ }
85
+ /** Days Oxy has to answer an erasure request ({@link isErasureRequest}). */
86
+ exports.ERASURE_REQUEST_DEADLINE_DAYS = 30;
87
+ /**
88
+ * Stable error codes a takedown produces elsewhere in the API. A file whose
89
+ * bytes are on the blocklist cannot be uploaded, imported or copied by anyone
90
+ * (HTTP 451).
91
+ */
92
+ exports.CONTENT_CLAIM_ERROR_CODES = {
93
+ /** The submission failed validation; `fields` names each problem. */
94
+ invalid: 'CONTENT_CLAIM_INVALID',
95
+ /** These exact bytes were taken down after a claim and cannot be stored again. */
96
+ contentBlocked: 'CONTENT_BLOCKED',
97
+ /** A counter-notice failed validation; `fields` names each problem. */
98
+ counterNoticeInvalid: 'CONTENT_CLAIM_COUNTER_NOTICE_INVALID',
99
+ /** The files named are blocked by more than one claim: name the claim's reference. */
100
+ counterNoticeAmbiguous: 'CONTENT_CLAIM_COUNTER_NOTICE_AMBIGUOUS',
101
+ /** This account already sent a counter-notice for this claim. */
102
+ counterNoticeExists: 'CONTENT_CLAIM_COUNTER_NOTICE_EXISTS',
103
+ };
104
+ /**
105
+ * A claim's reference as the claimant and the owner are sent it:
106
+ * `OXY-XXXX-XXXX`, Crockford base32 (no I, L, O or U).
107
+ */
108
+ exports.CONTENT_CLAIM_REFERENCE_PATTERN = /^OXY-[0-9A-HJKMNP-TV-Z]{4}-[0-9A-HJKMNP-TV-Z]{4}$/;
109
+ /** The bounds of an owner's counter-notice. The website fills its validation messages from these. */
110
+ exports.CONTENT_CLAIM_COUNTER_NOTICE_LIMITS = {
111
+ maxFileIds: 50,
112
+ maxFileId: 64,
113
+ maxName: 200,
114
+ maxAddress: 500,
115
+ minPhone: 5,
116
+ maxPhone: 40,
117
+ maxEmail: 254,
118
+ minMaterial: 10,
119
+ maxMaterial: 2000,
120
+ maxLocation: 2048,
121
+ minExplanation: 20,
122
+ maxExplanation: 5000,
123
+ maxSignature: 200,
124
+ };
125
+ /**
126
+ * The statements an owner's counter-notice makes, word for word — what the
127
+ * form shows beside each box (17 U.S.C. § 512(g)(3)(C) and (D), and what Oxy
128
+ * does with the notice). The API records {@link COUNTER_NOTICE_STATEMENT_VERSION}
129
+ * with every notice, so the wording a person agreed to can always be told
130
+ * apart from a later one. Change the text only together with the version.
131
+ */
132
+ exports.COUNTER_NOTICE_STATEMENTS = {
133
+ perjury: 'I swear, under penalty of perjury, that I have a good faith belief that the material identified above was removed or disabled as a result of a mistake or misidentification of the material to be removed or disabled.',
134
+ jurisdiction: 'I consent to the jurisdiction of the Federal District Court for the judicial district in which my address is located or, if my address is outside of the United States, any judicial district in which Oxy may be found.',
135
+ serviceOfProcess: 'I will accept service of process from the person who provided the notification of the claimed infringement, or an agent of such person.',
136
+ disclosure: 'I understand that Oxy sends a copy of this counter-notice, including my name and contact details, to the person who made the claim, as the law requires.',
137
+ };
138
+ /** The version of {@link COUNTER_NOTICE_STATEMENTS} in force. */
139
+ exports.COUNTER_NOTICE_STATEMENT_VERSION = '2026-10-16';
@@ -19,7 +19,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.deviceJoinCodeResponseCheck = exports.deviceBackgroundCredentialResponseCheck = exports.activeTokenCheck = exports.SESSION_ACCOUNTS_CHANGED_EVENT = exports.deviceDirectorySyncCheck = exports.deviceDirectoryCheck = exports.deviceActivateResponseCheck = exports.signedRecordEnvelopeCheck = exports.externalIdentityReferenceCheck = exports.loginResultCheck = exports.isLoopbackOrigin = exports.executeAgentKeyOperationCheck = exports.agentVerifyRequestCheck = exports.agentProofClaimsCheck = exports.agentKeyOperationResultCheck = exports.agentKeyOperationCheck = exports.agentKeyOperationChallengeCheck = exports.agentKeyListResponseCheck = exports.agentChallengeRequestCheck = exports.AGENT_PROOF_TTL_MS = exports.AGENT_PROOF_AUDIENCE = exports.AGENT_PROOF_ACTIONS = exports.ACCOUNT_AUTH_METHODS = exports.emailVerificationStartResponseCheck = exports.emailVerificationConfirmResponseCheck = exports.emailTicketCheck = exports.emailAddressCheck = exports.EMAIL_VERIFICATION_PURPOSES = exports.EMAIL_VERIFICATION_ERROR_CODES = exports.EMAIL_TICKET_TTL_MS = exports.EMAIL_CODE_TTL_MS = exports.EMAIL_CODE_MAX_ATTEMPTS = exports.EMAIL_CODE_LENGTH = exports.newlyAddedRetiredCategories = exports.kindAcceptsAccountCategories = exports.isSelectableAccountCategoryId = exports.isOperatorSwitchTargetKind = exports.isDelegatedActAsEligibleKind = exports.isAccountKind = exports.SELECTABLE_ACCOUNT_CATEGORY_IDS = exports.RETIRED_ACCOUNT_CATEGORY_IDS = exports.MAX_ACCOUNT_CATEGORIES = exports.CHILD_ACCOUNT_KINDS = exports.ACCOUNT_KINDS = exports.ACCOUNT_CATEGORY_KINDS = exports.ACCOUNT_CATEGORY_IDS = exports.parseContract = exports.formatCheckPath = exports.checkContract = exports.ContractCheckError = void 0;
20
20
  exports.subjectProductAccessCheck = exports.productSubscriptionsResponseCheck = exports.productSubscriptionCancellationResultCheck = exports.personalPlanCheckoutResultCheck = exports.personalPlanCheckoutRequestCheck = exports.personalPlanCatalogueCheck = exports.cancelProductSubscriptionCheck = exports.updateOrganizationCheck = exports.organizationNameCheck = exports.organizationListCheck = exports.organizationImportBatchResultCheck = exports.organizationExternalResolutionCheck = exports.organizationExternalCheck = exports.organizationCurationResultCheck = exports.organizationClaimReviewCheck = exports.organizationClaimListCheck = exports.organizationClaimInputCheck = exports.organizationClaimDetailCheck = exports.organizationClaimCheck = exports.organizationCheck = exports.organizationBatchCheck = exports.createOrganizationCheck = exports.ORGANIZATION_TYPES = exports.ORGANIZATION_STATUSES = exports.ORGANIZATION_NAME_MAX_LENGTH = exports.ORGANIZATION_ERROR_CODES = exports.ORGANIZATION_CLAIM_STATUSES = exports.ORGANIZATION_CLAIM_DECISIONS = exports.ORGANIZATION_ALIAS_KINDS = exports.canonicalJson = exports.buildIdentityProofMessage = exports.IDENTITY_PROOF_VERSION = exports.IDENTITY_PROOF_DOMAIN = exports.IDENTITY_PROOF_CHALLENGE_TTL_MS = exports.IDENTITY_PROOF_AUDIENCE = exports.IDENTITY_PROOF_ACTION_VALUES = exports.IDENTITY_PROOF_ACTIONS = exports.IDENTITY_ERROR_CODES = exports.parseIdentityLinkQrPayload = exports.identityLinkStateCheck = exports.identityLinkCreateResponseCheck = exports.buildIdentityLinkQrPayload = exports.IDENTITY_LINK_STATUSES = exports.IDENTITY_LINK_QR_PREFIX = exports.sessionAccountsChangedEventCheck = exports.deviceTokenMintResponseCheck = exports.deviceSessionSyncCheck = exports.deviceSessionStateCheck = exports.deviceRegisterResponseCheck = exports.deviceJoinResponseCheck = void 0;
21
21
  exports.secondFactorRequiredCheck = exports.reauthProofCheck = exports.normalizeEmailSignInCode = exports.isSecondFactorRequired = exports.isEmailSignInChooseAccount = exports.emailSignInStartResponseCheck = exports.emailSignInPendingCheck = exports.emailSignInLinkResponseCheck = exports.emailSignInChooseAccountCheck = exports.TOTP_PERIOD_SECONDS = exports.TOTP_DIGITS = exports.TOTP_BACKUP_CODE_COUNT = exports.SIGN_IN_ERROR_CODES = exports.SIGNIN_SECOND_FACTOR_TTL_MS = exports.SIGNIN_SECOND_FACTOR_MAX_ATTEMPTS = exports.REAUTH_ACTIONS = exports.PASSWORD_MIN_LENGTH = exports.PASSWORD_MAX_LENGTH = exports.EMAIL_SIGNIN_LONG_CODE_LENGTH = exports.EMAIL_SIGNIN_LONG_CODE_ALPHABET = exports.EMAIL_SIGNIN_LINK_TTL_MS = exports.EMAIL_SIGNIN_CHOICE_TTL_MS = exports.EMAIL_ACCOUNTS_MAX = exports.publicApplicationCheck = exports.supervisionStateCheck = exports.supervisionReviewInputCheck = exports.supervisionInviteInputCheck = exports.supervisionInvitationCheck = exports.supervisionContactsResponseCheck = exports.supervisionContactInputCheck = exports.supervisionAcceptInputCheck = exports.safetyPeopleResponseCheck = exports.safetyPeopleInputCheck = exports.safetyOrganizationsResponseCheck = exports.safetyOrganizationsInputCheck = exports.purchaseReviewInputCheck = exports.purchaseApprovalListCheck = exports.purchaseApprovalCheck = exports.profileAccessInputCheck = exports.profileAccessDecisionCheck = exports.SUPERVISION_STATUSES = exports.SUPERVISION_INVITATION_STATUSES = exports.SUPERVISION_CONSENT_VERSION = exports.SUPERVISED_ACTIONS = exports.SAFETY_POLICY_VERSION = exports.PURCHASE_APPROVAL_STATUSES = exports.isFullReputationBalance = exports.recommendationRequestCheck = exports.subscriptionCreditGrantsResponseCheck = exports.subjectProductAccessQueryCheck = void 0;
22
- exports.userNameCheck = exports.usernameCheckForAccountKind = exports.usernameCheck = exports.stripDisallowedUsernameCharacters = exports.botUsernameCheck = exports.applyBotUsernameSuffix = exports.USERNAME_PATTERN_SOURCE = exports.USERNAME_MIN_LENGTH = exports.USERNAME_MAX_LENGTH = exports.USERNAME_INVALID_MESSAGE = exports.RESERVED_USERNAME_MESSAGE = exports.RESERVED_USERNAMES = exports.NUMERIC_USERNAME_MESSAGE = exports.BOT_USERNAME_SUFFIX = exports.BOT_USERNAME_INVALID_MESSAGE = exports.totpEnrollResponseCheck = exports.totpBackupCodesResponseCheck = exports.signInMethodsCheck = void 0;
22
+ exports.isRightsClaim = exports.isErasureRequest = exports.OPEN_CONTENT_CLAIM_STATES = exports.ERASURE_REQUEST_DEADLINE_DAYS = exports.COUNTER_NOTICE_STATEMENTS = exports.COUNTER_NOTICE_STATEMENT_VERSION = exports.CONTENT_CLAIM_STATES = exports.CONTENT_CLAIM_REFERENCE_PATTERN = exports.CONTENT_CLAIM_LIMITS = exports.CONTENT_CLAIM_KINDS = exports.CONTENT_CLAIM_ERROR_CODES = exports.CONTENT_CLAIM_COUNTER_NOTICE_LIMITS = exports.CLOSED_CONTENT_CLAIM_STATES = exports.CLAIMANT_RELATIONSHIPS = exports.userNameCheck = exports.usernameCheckForAccountKind = exports.usernameCheck = exports.stripDisallowedUsernameCharacters = exports.botUsernameCheck = exports.applyBotUsernameSuffix = exports.USERNAME_PATTERN_SOURCE = exports.USERNAME_MIN_LENGTH = exports.USERNAME_MAX_LENGTH = exports.USERNAME_INVALID_MESSAGE = exports.RESERVED_USERNAME_MESSAGE = exports.RESERVED_USERNAMES = exports.NUMERIC_USERNAME_MESSAGE = exports.BOT_USERNAME_SUFFIX = exports.BOT_USERNAME_INVALID_MESSAGE = exports.totpEnrollResponseCheck = exports.totpBackupCodesResponseCheck = exports.signInMethodsCheck = void 0;
23
23
  var check_1 = require("./check");
24
24
  Object.defineProperty(exports, "ContractCheckError", { enumerable: true, get: function () { return check_1.ContractCheckError; } });
25
25
  Object.defineProperty(exports, "checkContract", { enumerable: true, get: function () { return check_1.checkContract; } });
@@ -209,3 +209,18 @@ Object.defineProperty(exports, "usernameCheck", { enumerable: true, get: functio
209
209
  Object.defineProperty(exports, "usernameCheckForAccountKind", { enumerable: true, get: function () { return username_1.usernameCheckForAccountKind; } });
210
210
  var userResponse_1 = require("./userResponse");
211
211
  Object.defineProperty(exports, "userNameCheck", { enumerable: true, get: function () { return userResponse_1.userNameCheck; } });
212
+ var contentClaims_1 = require("./contentClaims");
213
+ Object.defineProperty(exports, "CLAIMANT_RELATIONSHIPS", { enumerable: true, get: function () { return contentClaims_1.CLAIMANT_RELATIONSHIPS; } });
214
+ Object.defineProperty(exports, "CLOSED_CONTENT_CLAIM_STATES", { enumerable: true, get: function () { return contentClaims_1.CLOSED_CONTENT_CLAIM_STATES; } });
215
+ Object.defineProperty(exports, "CONTENT_CLAIM_COUNTER_NOTICE_LIMITS", { enumerable: true, get: function () { return contentClaims_1.CONTENT_CLAIM_COUNTER_NOTICE_LIMITS; } });
216
+ Object.defineProperty(exports, "CONTENT_CLAIM_ERROR_CODES", { enumerable: true, get: function () { return contentClaims_1.CONTENT_CLAIM_ERROR_CODES; } });
217
+ Object.defineProperty(exports, "CONTENT_CLAIM_KINDS", { enumerable: true, get: function () { return contentClaims_1.CONTENT_CLAIM_KINDS; } });
218
+ Object.defineProperty(exports, "CONTENT_CLAIM_LIMITS", { enumerable: true, get: function () { return contentClaims_1.CONTENT_CLAIM_LIMITS; } });
219
+ Object.defineProperty(exports, "CONTENT_CLAIM_REFERENCE_PATTERN", { enumerable: true, get: function () { return contentClaims_1.CONTENT_CLAIM_REFERENCE_PATTERN; } });
220
+ Object.defineProperty(exports, "CONTENT_CLAIM_STATES", { enumerable: true, get: function () { return contentClaims_1.CONTENT_CLAIM_STATES; } });
221
+ Object.defineProperty(exports, "COUNTER_NOTICE_STATEMENT_VERSION", { enumerable: true, get: function () { return contentClaims_1.COUNTER_NOTICE_STATEMENT_VERSION; } });
222
+ Object.defineProperty(exports, "COUNTER_NOTICE_STATEMENTS", { enumerable: true, get: function () { return contentClaims_1.COUNTER_NOTICE_STATEMENTS; } });
223
+ Object.defineProperty(exports, "ERASURE_REQUEST_DEADLINE_DAYS", { enumerable: true, get: function () { return contentClaims_1.ERASURE_REQUEST_DEADLINE_DAYS; } });
224
+ Object.defineProperty(exports, "OPEN_CONTENT_CLAIM_STATES", { enumerable: true, get: function () { return contentClaims_1.OPEN_CONTENT_CLAIM_STATES; } });
225
+ Object.defineProperty(exports, "isErasureRequest", { enumerable: true, get: function () { return contentClaims_1.isErasureRequest; } });
226
+ Object.defineProperty(exports, "isRightsClaim", { enumerable: true, get: function () { return contentClaims_1.isRightsClaim; } });
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.contentClaimCounterNoticeSchema = exports.CONTENT_CLAIM_COUNTER_NOTICE_VALIDATION_KEYS = exports.CONTENT_CLAIM_EVENT_ACTIONS = exports.CONTENT_CLAIM_TARGET_SOURCES = exports.CONTENT_CLAIM_TARGET_RESOLUTIONS = exports.contentClaimSubmissionSchema = exports.CONTENT_CLAIM_VALIDATION_KEYS = exports.isRightsClaim = exports.isErasureRequest = exports.OPEN_CONTENT_CLAIM_STATES = exports.ERASURE_REQUEST_DEADLINE_DAYS = exports.COUNTER_NOTICE_STATEMENTS = exports.COUNTER_NOTICE_STATEMENT_VERSION = exports.CONTENT_CLAIM_STATES = exports.CONTENT_CLAIM_REFERENCE_PATTERN = exports.CONTENT_CLAIM_LIMITS = exports.CONTENT_CLAIM_KINDS = exports.CONTENT_CLAIM_ERROR_CODES = exports.CONTENT_CLAIM_COUNTER_NOTICE_LIMITS = exports.CLOSED_CONTENT_CLAIM_STATES = exports.CLAIMANT_RELATIONSHIPS = void 0;
4
+ /**
5
+ * Content claims (ADR 0043 D10): the public "Report content / rights claim"
6
+ * intake, `POST /content-claims`, and the staff review of a claim.
7
+ *
8
+ * {@link contentClaimSubmissionSchema} is the request body the API parses and
9
+ * the Oxy website validates its form with before posting, so the form cannot
10
+ * accept what the API would answer 400 to. Every validation message is a
11
+ * stable KEY under `contentClaim.errors.*` (filled with
12
+ * {@link CONTENT_CLAIM_LIMITS} by whoever shows it), never English: the website
13
+ * translates the key, and the API answers its own English sentence for it in
14
+ * `fields`.
15
+ */
16
+ const zod_1 = require("zod");
17
+ // The Zod-free half of this contract lives in `./client/` (`@oxy.so/contracts/client`);
18
+ // it is re-exported here so the root entry carries the whole contract.
19
+ const contentClaims_1 = require("./client/contentClaims");
20
+ var contentClaims_2 = require("./client/contentClaims");
21
+ Object.defineProperty(exports, "CLAIMANT_RELATIONSHIPS", { enumerable: true, get: function () { return contentClaims_2.CLAIMANT_RELATIONSHIPS; } });
22
+ Object.defineProperty(exports, "CLOSED_CONTENT_CLAIM_STATES", { enumerable: true, get: function () { return contentClaims_2.CLOSED_CONTENT_CLAIM_STATES; } });
23
+ Object.defineProperty(exports, "CONTENT_CLAIM_COUNTER_NOTICE_LIMITS", { enumerable: true, get: function () { return contentClaims_2.CONTENT_CLAIM_COUNTER_NOTICE_LIMITS; } });
24
+ Object.defineProperty(exports, "CONTENT_CLAIM_ERROR_CODES", { enumerable: true, get: function () { return contentClaims_2.CONTENT_CLAIM_ERROR_CODES; } });
25
+ Object.defineProperty(exports, "CONTENT_CLAIM_KINDS", { enumerable: true, get: function () { return contentClaims_2.CONTENT_CLAIM_KINDS; } });
26
+ Object.defineProperty(exports, "CONTENT_CLAIM_LIMITS", { enumerable: true, get: function () { return contentClaims_2.CONTENT_CLAIM_LIMITS; } });
27
+ Object.defineProperty(exports, "CONTENT_CLAIM_REFERENCE_PATTERN", { enumerable: true, get: function () { return contentClaims_2.CONTENT_CLAIM_REFERENCE_PATTERN; } });
28
+ Object.defineProperty(exports, "CONTENT_CLAIM_STATES", { enumerable: true, get: function () { return contentClaims_2.CONTENT_CLAIM_STATES; } });
29
+ Object.defineProperty(exports, "COUNTER_NOTICE_STATEMENT_VERSION", { enumerable: true, get: function () { return contentClaims_2.COUNTER_NOTICE_STATEMENT_VERSION; } });
30
+ Object.defineProperty(exports, "COUNTER_NOTICE_STATEMENTS", { enumerable: true, get: function () { return contentClaims_2.COUNTER_NOTICE_STATEMENTS; } });
31
+ Object.defineProperty(exports, "ERASURE_REQUEST_DEADLINE_DAYS", { enumerable: true, get: function () { return contentClaims_2.ERASURE_REQUEST_DEADLINE_DAYS; } });
32
+ Object.defineProperty(exports, "OPEN_CONTENT_CLAIM_STATES", { enumerable: true, get: function () { return contentClaims_2.OPEN_CONTENT_CLAIM_STATES; } });
33
+ Object.defineProperty(exports, "isErasureRequest", { enumerable: true, get: function () { return contentClaims_2.isErasureRequest; } });
34
+ Object.defineProperty(exports, "isRightsClaim", { enumerable: true, get: function () { return contentClaims_2.isRightsClaim; } });
35
+ /** Every key a submission's validation can produce, under `contentClaim.errors.*`. */
36
+ exports.CONTENT_CLAIM_VALIDATION_KEYS = [
37
+ 'contentClaim.errors.kind',
38
+ 'contentClaim.errors.contentUrlsRequired',
39
+ 'contentClaim.errors.contentUrlsTooMany',
40
+ 'contentClaim.errors.contentUrlInvalid',
41
+ 'contentClaim.errors.descriptionShort',
42
+ 'contentClaim.errors.descriptionLong',
43
+ 'contentClaim.errors.originalWorkUrl',
44
+ 'contentClaim.errors.name',
45
+ 'contentClaim.errors.email',
46
+ 'contentClaim.errors.organization',
47
+ 'contentClaim.errors.relationship',
48
+ 'contentClaim.errors.goodFaith',
49
+ 'contentClaim.errors.accurate',
50
+ 'contentClaim.errors.signature',
51
+ ];
52
+ function isHttpsUrl(value) {
53
+ try {
54
+ const url = new URL(value);
55
+ return url.protocol === 'https:' && url.hostname.length > 0;
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
61
+ const httpsUrl = (message) => zod_1.z.string().trim().max(contentClaims_1.CONTENT_CLAIM_LIMITS.maxUrlLength, message).refine(isHttpsUrl, message);
62
+ /**
63
+ * `POST /content-claims` — a claim, as the claimant sends it. Strict: an
64
+ * unknown key is refused rather than dropped.
65
+ */
66
+ exports.contentClaimSubmissionSchema = zod_1.z
67
+ .object({
68
+ kind: zod_1.z.enum(contentClaims_1.CONTENT_CLAIM_KINDS, { message: 'contentClaim.errors.kind' }),
69
+ contentUrls: zod_1.z
70
+ .array(httpsUrl('contentClaim.errors.contentUrlInvalid'), {
71
+ message: 'contentClaim.errors.contentUrlsRequired',
72
+ })
73
+ .min(contentClaims_1.CONTENT_CLAIM_LIMITS.minUrls, 'contentClaim.errors.contentUrlsRequired')
74
+ .max(contentClaims_1.CONTENT_CLAIM_LIMITS.maxUrls, 'contentClaim.errors.contentUrlsTooMany'),
75
+ description: zod_1.z
76
+ .string({ message: 'contentClaim.errors.descriptionShort' })
77
+ .trim()
78
+ .min(contentClaims_1.CONTENT_CLAIM_LIMITS.minDescription, 'contentClaim.errors.descriptionShort')
79
+ .max(contentClaims_1.CONTENT_CLAIM_LIMITS.maxDescription, 'contentClaim.errors.descriptionLong'),
80
+ originalWorkUrl: httpsUrl('contentClaim.errors.originalWorkUrl').optional(),
81
+ claimant: zod_1.z
82
+ .object({
83
+ name: zod_1.z
84
+ .string({ message: 'contentClaim.errors.name' })
85
+ .trim()
86
+ .min(1, 'contentClaim.errors.name')
87
+ .max(contentClaims_1.CONTENT_CLAIM_LIMITS.maxName, 'contentClaim.errors.name'),
88
+ email: zod_1.z
89
+ .string({ message: 'contentClaim.errors.email' })
90
+ .trim()
91
+ .email('contentClaim.errors.email')
92
+ .max(contentClaims_1.CONTENT_CLAIM_LIMITS.maxEmail, 'contentClaim.errors.email'),
93
+ organization: zod_1.z
94
+ .string({ message: 'contentClaim.errors.organization' })
95
+ .trim()
96
+ .max(contentClaims_1.CONTENT_CLAIM_LIMITS.maxOrganization, 'contentClaim.errors.organization')
97
+ .optional(),
98
+ relationship: zod_1.z.enum(contentClaims_1.CLAIMANT_RELATIONSHIPS, {
99
+ message: 'contentClaim.errors.relationship',
100
+ }),
101
+ }, { message: 'contentClaim.errors.name' })
102
+ .strict(),
103
+ statements: zod_1.z
104
+ .object({
105
+ goodFaith: zod_1.z.literal(true, {
106
+ errorMap: () => ({ message: 'contentClaim.errors.goodFaith' }),
107
+ }),
108
+ accurate: zod_1.z.literal(true, {
109
+ errorMap: () => ({ message: 'contentClaim.errors.accurate' }),
110
+ }),
111
+ }, { message: 'contentClaim.errors.goodFaith' })
112
+ .strict(),
113
+ signature: zod_1.z
114
+ .string({ message: 'contentClaim.errors.signature' })
115
+ .trim()
116
+ .min(1, 'contentClaim.errors.signature')
117
+ .max(contentClaims_1.CONTENT_CLAIM_LIMITS.maxName, 'contentClaim.errors.signature'),
118
+ })
119
+ .strict();
120
+ // ---------------------------------------------------------------------------
121
+ // The staff review (`/content-claims` behind the `content:claims` capability)
122
+ // ---------------------------------------------------------------------------
123
+ /** How a target's URL was understood. */
124
+ exports.CONTENT_CLAIM_TARGET_RESOLUTIONS = [
125
+ /** An Oxy file: `cloud.oxy.so/<id>`, `/cdn/<id>`, `/assets/<id>…`, a stored key. */
126
+ 'file',
127
+ /** A page of an Oxy app or anything else: a person attaches the files it shows. */
128
+ 'unresolved',
129
+ ];
130
+ /** Who added a target: the claimant's URL, or staff attaching a file by id. */
131
+ exports.CONTENT_CLAIM_TARGET_SOURCES = ['claimant', 'staff'];
132
+ /** What the audit trail records. */
133
+ exports.CONTENT_CLAIM_EVENT_ACTIONS = [
134
+ 'submitted',
135
+ 'review_started',
136
+ 'targets_attached',
137
+ 'targets_blocked',
138
+ 'rejected',
139
+ 'counter_notice_recorded',
140
+ /** The owner of the blocked content sent a counter-notice themselves (`POST /content-claims/counter-notices`). */
141
+ 'counter_notice_submitted',
142
+ 'reinstated',
143
+ 'upheld',
144
+ 'note_added',
145
+ ];
146
+ // ---------------------------------------------------------------------------
147
+ // The owner's counter-notice (`POST /content-claims/counter-notices`)
148
+ // ---------------------------------------------------------------------------
149
+ /** Every key a counter-notice's validation can produce, under `contentClaim.counterNotice.errors.*`. */
150
+ exports.CONTENT_CLAIM_COUNTER_NOTICE_VALIDATION_KEYS = [
151
+ 'contentClaim.counterNotice.errors.claim',
152
+ 'contentClaim.counterNotice.errors.reference',
153
+ 'contentClaim.counterNotice.errors.claimId',
154
+ 'contentClaim.counterNotice.errors.fileIds',
155
+ 'contentClaim.counterNotice.errors.name',
156
+ 'contentClaim.counterNotice.errors.address',
157
+ 'contentClaim.counterNotice.errors.phone',
158
+ 'contentClaim.counterNotice.errors.email',
159
+ 'contentClaim.counterNotice.errors.materialDescription',
160
+ 'contentClaim.counterNotice.errors.materialLocation',
161
+ 'contentClaim.counterNotice.errors.explanation',
162
+ 'contentClaim.counterNotice.errors.perjury',
163
+ 'contentClaim.counterNotice.errors.jurisdiction',
164
+ 'contentClaim.counterNotice.errors.serviceOfProcess',
165
+ 'contentClaim.counterNotice.errors.disclosure',
166
+ 'contentClaim.counterNotice.errors.signature',
167
+ ];
168
+ const N = contentClaims_1.CONTENT_CLAIM_COUNTER_NOTICE_LIMITS;
169
+ const boundedText = (min, max, message) => zod_1.z.string({ message }).trim().min(min, message).max(max, message);
170
+ const affirmed = (message) => zod_1.z.literal(true, { errorMap: () => ({ message }) });
171
+ /**
172
+ * `POST /content-claims/counter-notices` — the owner of content a claim took
173
+ * down disputes it (17 U.S.C. § 512(g)(3)). Signed in: the API answers only
174
+ * for files the caller owns.
175
+ *
176
+ * Names the claim by its `reference` (the `OXY-XXXX-XXXX` the owner was
177
+ * emailed), its `claimId`, or the blocked `fileIds` — at least one. With
178
+ * `fileIds` the notice covers exactly those files; without, every one of the
179
+ * caller's files the claim blocked. Strict: an unknown key is refused.
180
+ */
181
+ exports.contentClaimCounterNoticeSchema = zod_1.z
182
+ .object({
183
+ reference: zod_1.z
184
+ .string({ message: 'contentClaim.counterNotice.errors.reference' })
185
+ .trim()
186
+ .toUpperCase()
187
+ .regex(contentClaims_1.CONTENT_CLAIM_REFERENCE_PATTERN, 'contentClaim.counterNotice.errors.reference')
188
+ .optional(),
189
+ claimId: zod_1.z
190
+ .string({ message: 'contentClaim.counterNotice.errors.claimId' })
191
+ .trim()
192
+ .uuid('contentClaim.counterNotice.errors.claimId')
193
+ .optional(),
194
+ fileIds: zod_1.z
195
+ .array(boundedText(1, N.maxFileId, 'contentClaim.counterNotice.errors.fileIds'), {
196
+ message: 'contentClaim.counterNotice.errors.fileIds',
197
+ })
198
+ .min(1, 'contentClaim.counterNotice.errors.fileIds')
199
+ .max(N.maxFileIds, 'contentClaim.counterNotice.errors.fileIds')
200
+ .optional(),
201
+ subscriber: zod_1.z
202
+ .object({
203
+ name: boundedText(1, N.maxName, 'contentClaim.counterNotice.errors.name'),
204
+ address: boundedText(1, N.maxAddress, 'contentClaim.counterNotice.errors.address'),
205
+ phone: boundedText(N.minPhone, N.maxPhone, 'contentClaim.counterNotice.errors.phone').regex(/^\+?[0-9 ().-]+$/, 'contentClaim.counterNotice.errors.phone'),
206
+ email: zod_1.z
207
+ .string({ message: 'contentClaim.counterNotice.errors.email' })
208
+ .trim()
209
+ .email('contentClaim.counterNotice.errors.email')
210
+ .max(N.maxEmail, 'contentClaim.counterNotice.errors.email'),
211
+ }, { message: 'contentClaim.counterNotice.errors.name' })
212
+ .strict(),
213
+ material: zod_1.z
214
+ .object({
215
+ /** What was removed. */
216
+ description: boundedText(N.minMaterial, N.maxMaterial, 'contentClaim.counterNotice.errors.materialDescription'),
217
+ /** Where it appeared before it was removed (a URL, or where in an app). */
218
+ location: boundedText(1, N.maxLocation, 'contentClaim.counterNotice.errors.materialLocation'),
219
+ }, { message: 'contentClaim.counterNotice.errors.materialDescription' })
220
+ .strict(),
221
+ /** Why it was a mistake or a misidentification, in the owner's words. */
222
+ explanation: boundedText(N.minExplanation, N.maxExplanation, 'contentClaim.counterNotice.errors.explanation'),
223
+ /** Each of `COUNTER_NOTICE_STATEMENTS`, affirmed. */
224
+ statements: zod_1.z
225
+ .object({
226
+ perjury: affirmed('contentClaim.counterNotice.errors.perjury'),
227
+ jurisdiction: affirmed('contentClaim.counterNotice.errors.jurisdiction'),
228
+ serviceOfProcess: affirmed('contentClaim.counterNotice.errors.serviceOfProcess'),
229
+ disclosure: affirmed('contentClaim.counterNotice.errors.disclosure'),
230
+ }, { message: 'contentClaim.counterNotice.errors.perjury' })
231
+ .strict(),
232
+ /** The owner's full legal name, typed as their signature. */
233
+ signature: boundedText(1, N.maxSignature, 'contentClaim.counterNotice.errors.signature'),
234
+ })
235
+ .strict()
236
+ .superRefine((value, ctx) => {
237
+ if (value.reference === undefined &&
238
+ value.claimId === undefined &&
239
+ value.fileIds === undefined) {
240
+ ctx.addIssue({
241
+ code: zod_1.z.ZodIssueCode.custom,
242
+ path: ['reference'],
243
+ message: 'contentClaim.counterNotice.errors.claim',
244
+ });
245
+ }
246
+ });
package/dist/cjs/index.js CHANGED
@@ -899,3 +899,4 @@ var serviceToken_1 = require("./serviceToken");
899
899
  Object.defineProperty(exports, "serviceTokenScopesSchema", { enumerable: true, get: function () { return serviceToken_1.serviceTokenScopesSchema; } });
900
900
  Object.defineProperty(exports, "serviceTokenOptionsSchema", { enumerable: true, get: function () { return serviceToken_1.serviceTokenOptionsSchema; } });
901
901
  __exportStar(require("./applicationRoles"), exports);
902
+ __exportStar(require("./contentClaims"), exports);
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Content claims (ADR 0043 D10) — the constants of the public "Report content
3
+ * / rights claim" intake and of a claim's review, without Zod. Schemas:
4
+ * `../contentClaims.ts`.
5
+ *
6
+ * Part of `@oxy.so/contracts/client`: never import `zod` here (see `./check.ts`).
7
+ */
8
+ /** What a claim asserts. */
9
+ export const CONTENT_CLAIM_KINDS = [
10
+ 'copyright',
11
+ 'trademark',
12
+ 'privacy',
13
+ 'illegal_content',
14
+ 'other',
15
+ ];
16
+ /** Who the claimant is to the content. */
17
+ export const CLAIMANT_RELATIONSHIPS = [
18
+ 'rights_holder',
19
+ 'authorized_agent',
20
+ 'affected_person',
21
+ 'other',
22
+ ];
23
+ /** The bounds of a submission. The website fills its validation messages from these. */
24
+ export const CONTENT_CLAIM_LIMITS = {
25
+ minUrls: 1,
26
+ maxUrls: 20,
27
+ maxUrlLength: 2048,
28
+ minDescription: 20,
29
+ maxDescription: 5000,
30
+ maxName: 200,
31
+ maxOrganization: 200,
32
+ maxEmail: 254,
33
+ };
34
+ /**
35
+ * Where a claim is in its review.
36
+ *
37
+ * `received → reviewing → actioned | rejected`; an actioned claim can be
38
+ * answered by the content's owner (`counter_noticed`), which ends either in
39
+ * `reinstated` (the content is served again) or `upheld` (it stays blocked).
40
+ * A claim can also be rejected straight from `received`.
41
+ */
42
+ export const CONTENT_CLAIM_STATES = [
43
+ 'received',
44
+ 'reviewing',
45
+ 'actioned',
46
+ 'rejected',
47
+ 'counter_noticed',
48
+ 'reinstated',
49
+ 'upheld',
50
+ ];
51
+ /** The states in which a claim is still open: its evidence is kept and its blocks can change. */
52
+ export const OPEN_CONTENT_CLAIM_STATES = [
53
+ 'received',
54
+ 'reviewing',
55
+ 'actioned',
56
+ 'counter_noticed',
57
+ ];
58
+ /** The states a claim ends in. */
59
+ export const CLOSED_CONTENT_CLAIM_STATES = [
60
+ 'rejected',
61
+ 'reinstated',
62
+ 'upheld',
63
+ ];
64
+ /**
65
+ * The kinds whose claimant asserts a right in a work or a mark. Only these
66
+ * carry the link to the original — a privacy or illegal-content report
67
+ * asserts no ownership.
68
+ */
69
+ export function isRightsClaim(kind) {
70
+ return kind === 'copyright' || kind === 'trademark';
71
+ }
72
+ /**
73
+ * A request to erase the claimant's OWN personal data (GDPR art. 17): a
74
+ * privacy claim made by the person it is about. Oxy must answer it within one
75
+ * month (art. 12(3)); the claim carries that deadline.
76
+ */
77
+ export function isErasureRequest(kind, relationship) {
78
+ return kind === 'privacy' && relationship === 'affected_person';
79
+ }
80
+ /** Days Oxy has to answer an erasure request ({@link isErasureRequest}). */
81
+ export const ERASURE_REQUEST_DEADLINE_DAYS = 30;
82
+ /**
83
+ * Stable error codes a takedown produces elsewhere in the API. A file whose
84
+ * bytes are on the blocklist cannot be uploaded, imported or copied by anyone
85
+ * (HTTP 451).
86
+ */
87
+ export const CONTENT_CLAIM_ERROR_CODES = {
88
+ /** The submission failed validation; `fields` names each problem. */
89
+ invalid: 'CONTENT_CLAIM_INVALID',
90
+ /** These exact bytes were taken down after a claim and cannot be stored again. */
91
+ contentBlocked: 'CONTENT_BLOCKED',
92
+ /** A counter-notice failed validation; `fields` names each problem. */
93
+ counterNoticeInvalid: 'CONTENT_CLAIM_COUNTER_NOTICE_INVALID',
94
+ /** The files named are blocked by more than one claim: name the claim's reference. */
95
+ counterNoticeAmbiguous: 'CONTENT_CLAIM_COUNTER_NOTICE_AMBIGUOUS',
96
+ /** This account already sent a counter-notice for this claim. */
97
+ counterNoticeExists: 'CONTENT_CLAIM_COUNTER_NOTICE_EXISTS',
98
+ };
99
+ /**
100
+ * A claim's reference as the claimant and the owner are sent it:
101
+ * `OXY-XXXX-XXXX`, Crockford base32 (no I, L, O or U).
102
+ */
103
+ export const CONTENT_CLAIM_REFERENCE_PATTERN = /^OXY-[0-9A-HJKMNP-TV-Z]{4}-[0-9A-HJKMNP-TV-Z]{4}$/;
104
+ /** The bounds of an owner's counter-notice. The website fills its validation messages from these. */
105
+ export const CONTENT_CLAIM_COUNTER_NOTICE_LIMITS = {
106
+ maxFileIds: 50,
107
+ maxFileId: 64,
108
+ maxName: 200,
109
+ maxAddress: 500,
110
+ minPhone: 5,
111
+ maxPhone: 40,
112
+ maxEmail: 254,
113
+ minMaterial: 10,
114
+ maxMaterial: 2000,
115
+ maxLocation: 2048,
116
+ minExplanation: 20,
117
+ maxExplanation: 5000,
118
+ maxSignature: 200,
119
+ };
120
+ /**
121
+ * The statements an owner's counter-notice makes, word for word — what the
122
+ * form shows beside each box (17 U.S.C. § 512(g)(3)(C) and (D), and what Oxy
123
+ * does with the notice). The API records {@link COUNTER_NOTICE_STATEMENT_VERSION}
124
+ * with every notice, so the wording a person agreed to can always be told
125
+ * apart from a later one. Change the text only together with the version.
126
+ */
127
+ export const COUNTER_NOTICE_STATEMENTS = {
128
+ perjury: 'I swear, under penalty of perjury, that I have a good faith belief that the material identified above was removed or disabled as a result of a mistake or misidentification of the material to be removed or disabled.',
129
+ jurisdiction: 'I consent to the jurisdiction of the Federal District Court for the judicial district in which my address is located or, if my address is outside of the United States, any judicial district in which Oxy may be found.',
130
+ serviceOfProcess: 'I will accept service of process from the person who provided the notification of the claimed infringement, or an agent of such person.',
131
+ disclosure: 'I understand that Oxy sends a copy of this counter-notice, including my name and contact details, to the person who made the claim, as the law requires.',
132
+ };
133
+ /** The version of {@link COUNTER_NOTICE_STATEMENTS} in force. */
134
+ export const COUNTER_NOTICE_STATEMENT_VERSION = '2026-10-16';
@@ -35,3 +35,4 @@ export { publicApplicationCheck } from './sessionStatus.js';
35
35
  export { EMAIL_ACCOUNTS_MAX, EMAIL_SIGNIN_CHOICE_TTL_MS, EMAIL_SIGNIN_LINK_TTL_MS, EMAIL_SIGNIN_LONG_CODE_ALPHABET, EMAIL_SIGNIN_LONG_CODE_LENGTH, PASSWORD_MAX_LENGTH, PASSWORD_MIN_LENGTH, REAUTH_ACTIONS, SIGNIN_SECOND_FACTOR_MAX_ATTEMPTS, SIGNIN_SECOND_FACTOR_TTL_MS, SIGN_IN_ERROR_CODES, TOTP_BACKUP_CODE_COUNT, TOTP_DIGITS, TOTP_PERIOD_SECONDS, emailSignInChooseAccountCheck, emailSignInLinkResponseCheck, emailSignInPendingCheck, emailSignInStartResponseCheck, isEmailSignInChooseAccount, isSecondFactorRequired, normalizeEmailSignInCode, reauthProofCheck, secondFactorRequiredCheck, signInMethodsCheck, totpBackupCodesResponseCheck, totpEnrollResponseCheck, } from './signIn.js';
36
36
  export { BOT_USERNAME_INVALID_MESSAGE, BOT_USERNAME_SUFFIX, NUMERIC_USERNAME_MESSAGE, RESERVED_USERNAMES, RESERVED_USERNAME_MESSAGE, USERNAME_INVALID_MESSAGE, USERNAME_MAX_LENGTH, USERNAME_MIN_LENGTH, USERNAME_PATTERN_SOURCE, applyBotUsernameSuffix, botUsernameCheck, stripDisallowedUsernameCharacters, usernameCheck, usernameCheckForAccountKind, } from './username.js';
37
37
  export { userNameCheck } from './userResponse.js';
38
+ export { CLAIMANT_RELATIONSHIPS, CLOSED_CONTENT_CLAIM_STATES, CONTENT_CLAIM_COUNTER_NOTICE_LIMITS, CONTENT_CLAIM_ERROR_CODES, CONTENT_CLAIM_KINDS, CONTENT_CLAIM_LIMITS, CONTENT_CLAIM_REFERENCE_PATTERN, CONTENT_CLAIM_STATES, COUNTER_NOTICE_STATEMENT_VERSION, COUNTER_NOTICE_STATEMENTS, ERASURE_REQUEST_DEADLINE_DAYS, OPEN_CONTENT_CLAIM_STATES, isErasureRequest, isRightsClaim, } from './contentClaims.js';