@ttt-productions/ttt-core 0.78.2 → 0.78.4
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/constants/business-admin.d.ts +3 -0
- package/dist/constants/business-admin.d.ts.map +1 -1
- package/dist/constants/business-admin.js +3 -0
- package/dist/constants/business-admin.js.map +1 -1
- package/dist/constants/business-content.d.ts +40 -2
- package/dist/constants/business-content.d.ts.map +1 -1
- package/dist/constants/business-content.js +52 -9
- package/dist/constants/business-content.js.map +1 -1
- package/dist/doc-schemas/chat-sync.d.ts +1 -1
- package/dist/doc-schemas/media-activation-jobs.d.ts +1 -1
- package/dist/doc-schemas/media-assets.d.ts +7 -7
- package/dist/doc-schemas/moderation.d.ts +2 -2
- package/dist/doc-schemas/ncii/requests.d.ts +1 -1
- package/dist/doc-schemas/notifications.d.ts +9 -9
- package/dist/doc-schemas/notifications.d.ts.map +1 -1
- package/dist/doc-schemas/notifications.js +14 -38
- package/dist/doc-schemas/notifications.js.map +1 -1
- package/dist/doc-schemas/registry.d.ts +13 -13
- package/dist/doc-schemas/registry.d.ts.map +1 -1
- package/dist/doc-schemas/registry.js +3 -0
- package/dist/doc-schemas/registry.js.map +1 -1
- package/dist/doc-schemas/safety/case.d.ts +20 -0
- package/dist/doc-schemas/safety/case.d.ts.map +1 -1
- package/dist/doc-schemas/safety/case.js +13 -1
- package/dist/doc-schemas/safety/case.js.map +1 -1
- package/dist/doc-schemas/safety/evidence.d.ts +12 -4
- package/dist/doc-schemas/safety/evidence.d.ts.map +1 -1
- package/dist/doc-schemas/safety/evidence.js +18 -4
- package/dist/doc-schemas/safety/evidence.js.map +1 -1
- package/dist/doc-schemas/safety/foundation.d.ts +2 -2
- package/dist/doc-schemas/safety/holds.d.ts +1 -1
- package/dist/doc-schemas/social.d.ts +3 -3
- package/dist/media/atoms.d.ts +2 -2
- package/dist/media/target-info.d.ts +1 -3
- package/dist/media/target-info.d.ts.map +1 -1
- package/dist/media/target-info.js +14 -2
- package/dist/media/target-info.js.map +1 -1
- package/dist/paths/collections.d.ts +1 -0
- package/dist/paths/collections.d.ts.map +1 -1
- package/dist/paths/collections.js +2 -0
- package/dist/paths/collections.js.map +1 -1
- package/dist/paths/path-builders.d.ts +14 -0
- package/dist/paths/path-builders.d.ts.map +1 -1
- package/dist/paths/path-builders.js +29 -0
- package/dist/paths/path-builders.js.map +1 -1
- package/dist/safety/active-safety-case-alert.d.ts +33 -0
- package/dist/safety/active-safety-case-alert.d.ts.map +1 -0
- package/dist/safety/active-safety-case-alert.js +49 -0
- package/dist/safety/active-safety-case-alert.js.map +1 -0
- package/dist/safety/index.d.ts +4 -0
- package/dist/safety/index.d.ts.map +1 -0
- package/dist/safety/index.js +7 -0
- package/dist/safety/index.js.map +1 -0
- package/dist/safety/ncii-intake-derivations.d.ts +63 -0
- package/dist/safety/ncii-intake-derivations.d.ts.map +1 -0
- package/dist/safety/ncii-intake-derivations.js +227 -0
- package/dist/safety/ncii-intake-derivations.js.map +1 -0
- package/dist/safety/resource-keys.d.ts +60 -0
- package/dist/safety/resource-keys.d.ts.map +1 -0
- package/dist/safety/resource-keys.js +122 -0
- package/dist/safety/resource-keys.js.map +1 -0
- package/dist/schemas/admin-dispatch-actions.d.ts +4 -0
- package/dist/schemas/admin-dispatch-actions.d.ts.map +1 -1
- package/dist/schemas/admin-dispatch-actions.js +5 -0
- package/dist/schemas/admin-dispatch-actions.js.map +1 -1
- package/dist/schemas/admin.d.ts +78 -0
- package/dist/schemas/admin.d.ts.map +1 -1
- package/dist/schemas/admin.js +69 -1
- package/dist/schemas/admin.js.map +1 -1
- package/dist/schemas/chat.d.ts +51 -0
- package/dist/schemas/chat.d.ts.map +1 -1
- package/dist/schemas/chat.js +44 -1
- package/dist/schemas/chat.js.map +1 -1
- package/dist/schemas/safety.d.ts +67 -0
- package/dist/schemas/safety.d.ts.map +1 -1
- package/dist/schemas/safety.js +63 -0
- package/dist/schemas/safety.js.map +1 -1
- package/dist/schemas/social.d.ts +2 -2
- package/dist/schemas/utility.d.ts +4 -0
- package/dist/schemas/utility.d.ts.map +1 -1
- package/dist/schemas/utility.js +5 -0
- package/dist/schemas/utility.js.map +1 -1
- package/dist/upload-variables/square-streetz-post-variables.d.ts +1 -1
- package/package.json +10 -6
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { resourceKeyHash } from './resource-keys.js';
|
|
2
|
+
import type { TakeItDownFieldCode, TakeItDownRequesterRole, TargetLocatorV1, TargetLocatorSummaryV1 } from '../doc-schemas/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* sha256-hex chokepoint. Aliased to `resourceKeyHash` (the single canonical hashing
|
|
5
|
+
* helper in `./resource-keys`) so the whole `./safety` surface has ONE sha256
|
|
6
|
+
* implementation, never two. Named `sha256Hex` here because these intake derivations
|
|
7
|
+
* hash arbitrary keyspace strings, not resource keys.
|
|
8
|
+
*/
|
|
9
|
+
export declare const sha256Hex: typeof resourceKeyHash;
|
|
10
|
+
/** Deterministic `nciiTemporaryHolds/{holdId}` doc id for a request. ONE definition shared
|
|
11
|
+
* by intake (which writes the row) and the removal saga (which reads its `target` locator as
|
|
12
|
+
* the fallback when a public-form request has no case-linked allegation). */
|
|
13
|
+
export declare function tempHoldId(requestId: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Canonical, collision-resistant key for a request target. For a resolvable
|
|
16
|
+
* TTT-hosted locator the key is the locator discriminant + its identity fields;
|
|
17
|
+
* for an external/unresolvable locator (a bare URL or free text) it is the
|
|
18
|
+
* `url`/`additionalText` payload. The SAME logical target ALWAYS normalizes to the
|
|
19
|
+
* SAME key so two submissions about the same content with the same idempotencyKey
|
|
20
|
+
* resolve to ONE request doc, and two DIFFERENT targets never collide.
|
|
21
|
+
*
|
|
22
|
+
* No JSON — a flat unit-separator-joined string (the separator is illegal in any
|
|
23
|
+
* id/url field) is stable by construction (no key-ordering ambiguity).
|
|
24
|
+
*/
|
|
25
|
+
export declare function normalizedTargetKey(locator: TargetLocatorV1): string;
|
|
26
|
+
/** Best-effort URL normalization for the external-locator key. A non-parseable
|
|
27
|
+
* string is lowercased + trimmed (still deterministic). NEVER throws. */
|
|
28
|
+
export declare function normalizeExternalUrl(raw: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* [H-07] The deterministic intake requestId:
|
|
31
|
+
* sha256('takeItDownRequest:v1:' + idempotencyKey + ':' + normalizedTargetKey).
|
|
32
|
+
* A retry with the SAME client idempotencyKey + the SAME target re-derives the SAME
|
|
33
|
+
* id, so the create-if-absent transaction is a no-op and re-returns the same receipt
|
|
34
|
+
* (never double-arms a clock / double-commits a hold).
|
|
35
|
+
*/
|
|
36
|
+
export declare function deterministicRequestId(idempotencyKey: string, targetKey: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* The opaque public `requestReference` printed on the one-time receipt and stored on the
|
|
39
|
+
* public-status projection. Since the status token was removed, this is a deterministic
|
|
40
|
+
* derivation of the internal `requestId` — a separate sha256 so the raw `requestId` is
|
|
41
|
+
* never recoverable from the reference (which appears on the receipt / projection).
|
|
42
|
+
* 32 hex chars is ample entropy for an opaque, non-enumerable capability.
|
|
43
|
+
*/
|
|
44
|
+
export declare function deriveRequestReference(requestId: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Deterministic hash of the cumulative request state as of a submission — recorded
|
|
47
|
+
* on `TakeItDownSubmissionV1.cumulativeRequestSnapshotHash`. Built from the SORTED
|
|
48
|
+
* supplied field codes + the normalized target key + the requester role so the same
|
|
49
|
+
* cumulative state always fingerprints identically (append-order independent).
|
|
50
|
+
*/
|
|
51
|
+
export declare function cumulativeSnapshotHash(args: {
|
|
52
|
+
requesterRole: TakeItDownRequesterRole;
|
|
53
|
+
targetKey: string;
|
|
54
|
+
suppliedFieldCodes: readonly TakeItDownFieldCode[];
|
|
55
|
+
}): string;
|
|
56
|
+
/** A short, non-sensitive surface label per locator kind (no ids, no narrative). */
|
|
57
|
+
export declare function surfaceLabelFor(locator: TargetLocatorV1): string;
|
|
58
|
+
/** Build the privacy-safe `TargetLocatorSummaryV1` (kind + surface label +
|
|
59
|
+
* whether a TTT-hosted target was server-resolved). NEVER the narrative or ids. */
|
|
60
|
+
export declare function targetLocatorSummary(locator: TargetLocatorV1, hasResolvedTarget: boolean): TargetLocatorSummaryV1;
|
|
61
|
+
/** True when the locator points at a TTT-hosted surface (server-resolvable). */
|
|
62
|
+
export declare function isTttHostedLocator(locator: TargetLocatorV1): boolean;
|
|
63
|
+
//# sourceMappingURL=ncii-intake-derivations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ncii-intake-derivations.d.ts","sourceRoot":"","sources":["../../src/safety/ncii-intake-derivations.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EACV,mBAAmB,EACnB,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAEjC;;;;;GAKG;AACH,eAAO,MAAM,SAAS,wBAAkB,CAAC;AAczC;;8EAE8E;AAC9E,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CA4CpE;AAED;0EAC0E;AAC1E,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUxD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAExF;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEhE;AAMD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,aAAa,EAAE,uBAAuB,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACpD,GAAG,MAAM,CAKT;AAMD,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAyChE;AAED;oFACoF;AACpF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,OAAO,GACzB,sBAAsB,CAMxB;AAmBD,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAEpE"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// Shared NCII / TAKE IT DOWN intake derivations (Trust & Safety IMPLEMENTATION_PLAN
|
|
2
|
+
// Phase NCII-2/3/4, Appendix A §A11). Pure, deterministic id/key/summary derivations
|
|
3
|
+
// used by BOTH the public Next.js intake route and the Cloud Functions deadline/scan
|
|
4
|
+
// workers. These used to be hand-mirrored in two app TS projects (the Cloud Functions
|
|
5
|
+
// graph AND the App Hosting route graph, which cannot cross-import). This is now the ONE
|
|
6
|
+
// canonical declaration (Rule 36 / Cross-Boundary Type Invariant): both module graphs
|
|
7
|
+
// import these derivations from ttt-core so the deterministic id/key contracts can never
|
|
8
|
+
// drift between the two runtimes.
|
|
9
|
+
//
|
|
10
|
+
// These are LOAD-BEARING KEYSPACE CONTRACTS. A formula (or version-tag) change re-keys
|
|
11
|
+
// EVERY existing intake request doc / receipt / snapshot — treat any such change as a
|
|
12
|
+
// breaking migration of the intake keyspace, never a routine edit. The per-function
|
|
13
|
+
// version-bump warnings below are not decorative.
|
|
14
|
+
//
|
|
15
|
+
// node:crypto sha256 keeps this pure + server-safe: this module lives behind the
|
|
16
|
+
// `./safety` entry (never on the main barrel), so the frontend bundle never loads it.
|
|
17
|
+
// The completeness predicate + intake-facts shape are NOT here — they are canonical on
|
|
18
|
+
// `./doc-schemas` (beside `computeCompleteness`); import those from there.
|
|
19
|
+
import { resourceKeyHash } from './resource-keys.js';
|
|
20
|
+
/**
|
|
21
|
+
* sha256-hex chokepoint. Aliased to `resourceKeyHash` (the single canonical hashing
|
|
22
|
+
* helper in `./resource-keys`) so the whole `./safety` surface has ONE sha256
|
|
23
|
+
* implementation, never two. Named `sha256Hex` here because these intake derivations
|
|
24
|
+
* hash arbitrary keyspace strings, not resource keys.
|
|
25
|
+
*/
|
|
26
|
+
export const sha256Hex = resourceKeyHash;
|
|
27
|
+
/** Unit separator — illegal in any id/url/field we join, so a flat separator-joined
|
|
28
|
+
* string is stable by construction (no key-ordering ambiguity, no JSON). */
|
|
29
|
+
const SEP = '\x1f';
|
|
30
|
+
// ===========================================================================
|
|
31
|
+
// Deterministic ids ([H-07] idempotent intake)
|
|
32
|
+
// ===========================================================================
|
|
33
|
+
/** Version tag for the deterministic intake requestId. A bump re-keys EVERY
|
|
34
|
+
* request doc id — treat as a breaking migration of the intake keyspace. */
|
|
35
|
+
const REQUEST_ID_VERSION = 'takeItDownRequest:v1';
|
|
36
|
+
/** Deterministic `nciiTemporaryHolds/{holdId}` doc id for a request. ONE definition shared
|
|
37
|
+
* by intake (which writes the row) and the removal saga (which reads its `target` locator as
|
|
38
|
+
* the fallback when a public-form request has no case-linked allegation). */
|
|
39
|
+
export function tempHoldId(requestId) {
|
|
40
|
+
return sha256Hex(`nciiTemporaryHold:v1:${requestId}`);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Canonical, collision-resistant key for a request target. For a resolvable
|
|
44
|
+
* TTT-hosted locator the key is the locator discriminant + its identity fields;
|
|
45
|
+
* for an external/unresolvable locator (a bare URL or free text) it is the
|
|
46
|
+
* `url`/`additionalText` payload. The SAME logical target ALWAYS normalizes to the
|
|
47
|
+
* SAME key so two submissions about the same content with the same idempotencyKey
|
|
48
|
+
* resolve to ONE request doc, and two DIFFERENT targets never collide.
|
|
49
|
+
*
|
|
50
|
+
* No JSON — a flat unit-separator-joined string (the separator is illegal in any
|
|
51
|
+
* id/url field) is stable by construction (no key-ordering ambiguity).
|
|
52
|
+
*/
|
|
53
|
+
export function normalizedTargetKey(locator) {
|
|
54
|
+
const k = locator.kind;
|
|
55
|
+
switch (locator.kind) {
|
|
56
|
+
case 'mediaAsset':
|
|
57
|
+
return [k, locator.mediaAssetId].join(SEP);
|
|
58
|
+
case 'hallItem':
|
|
59
|
+
return [k, locator.hallItemId, locator.subItemId ?? ''].join(SEP);
|
|
60
|
+
case 'squarePost':
|
|
61
|
+
return [k, locator.postId].join(SEP);
|
|
62
|
+
case 'profileImage':
|
|
63
|
+
return [k, locator.profileUid].join(SEP);
|
|
64
|
+
case 'username':
|
|
65
|
+
return [k, locator.profileUid].join(SEP);
|
|
66
|
+
case 'craftSkill':
|
|
67
|
+
return [k, locator.profileUid, locator.craftSkillId].join(SEP);
|
|
68
|
+
case 'commissionListing':
|
|
69
|
+
return [k, locator.commissionListingId].join(SEP);
|
|
70
|
+
case 'audition':
|
|
71
|
+
return [k, locator.auditionId].join(SEP);
|
|
72
|
+
case 'auditionEntry':
|
|
73
|
+
return [k, locator.auditionId, locator.auditionEntryId].join(SEP);
|
|
74
|
+
case 'guildInviteMessage':
|
|
75
|
+
return [k, locator.channelId, locator.messageId].join(SEP);
|
|
76
|
+
case 'chatAttachment':
|
|
77
|
+
return [k, locator.channelId, locator.messageId, locator.attachmentId].join(SEP);
|
|
78
|
+
case 'guildChatMessage':
|
|
79
|
+
return [k, locator.channelId, locator.messageId].join(SEP);
|
|
80
|
+
case 'adminWorkMessage':
|
|
81
|
+
return [k, locator.adminDispatchId, locator.messageId].join(SEP);
|
|
82
|
+
case 'commissionProposal':
|
|
83
|
+
return [k, locator.commissionListingId, locator.commissionProposalId].join(SEP);
|
|
84
|
+
case 'workProject':
|
|
85
|
+
return [k, locator.workProjectId].join(SEP);
|
|
86
|
+
case 'workAsset':
|
|
87
|
+
return [k, locator.workProjectId, locator.workAssetId].join(SEP);
|
|
88
|
+
case 'workRealm':
|
|
89
|
+
return [k, locator.workRealmId].join(SEP);
|
|
90
|
+
case 'url':
|
|
91
|
+
// Normalize the URL (trim + lowercase scheme/host) so trivially-different
|
|
92
|
+
// spellings of the same external link collapse to one request.
|
|
93
|
+
return [k, normalizeExternalUrl(locator.url)].join(SEP);
|
|
94
|
+
case 'additionalText':
|
|
95
|
+
return [k, locator.textRef].join(SEP);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Best-effort URL normalization for the external-locator key. A non-parseable
|
|
99
|
+
* string is lowercased + trimmed (still deterministic). NEVER throws. */
|
|
100
|
+
export function normalizeExternalUrl(raw) {
|
|
101
|
+
const trimmed = raw.trim();
|
|
102
|
+
try {
|
|
103
|
+
const u = new URL(trimmed);
|
|
104
|
+
u.protocol = u.protocol.toLowerCase();
|
|
105
|
+
u.hostname = u.hostname.toLowerCase();
|
|
106
|
+
return u.toString();
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return trimmed.toLowerCase();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* [H-07] The deterministic intake requestId:
|
|
114
|
+
* sha256('takeItDownRequest:v1:' + idempotencyKey + ':' + normalizedTargetKey).
|
|
115
|
+
* A retry with the SAME client idempotencyKey + the SAME target re-derives the SAME
|
|
116
|
+
* id, so the create-if-absent transaction is a no-op and re-returns the same receipt
|
|
117
|
+
* (never double-arms a clock / double-commits a hold).
|
|
118
|
+
*/
|
|
119
|
+
export function deterministicRequestId(idempotencyKey, targetKey) {
|
|
120
|
+
return sha256Hex(`${REQUEST_ID_VERSION}:${idempotencyKey}:${targetKey}`);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The opaque public `requestReference` printed on the one-time receipt and stored on the
|
|
124
|
+
* public-status projection. Since the status token was removed, this is a deterministic
|
|
125
|
+
* derivation of the internal `requestId` — a separate sha256 so the raw `requestId` is
|
|
126
|
+
* never recoverable from the reference (which appears on the receipt / projection).
|
|
127
|
+
* 32 hex chars is ample entropy for an opaque, non-enumerable capability.
|
|
128
|
+
*/
|
|
129
|
+
export function deriveRequestReference(requestId) {
|
|
130
|
+
return sha256Hex(`takeItDownRequestRef:v1:${requestId}`).slice(0, 32);
|
|
131
|
+
}
|
|
132
|
+
// ===========================================================================
|
|
133
|
+
// Cumulative submission snapshot hash (the immutable receipt fingerprint)
|
|
134
|
+
// ===========================================================================
|
|
135
|
+
/**
|
|
136
|
+
* Deterministic hash of the cumulative request state as of a submission — recorded
|
|
137
|
+
* on `TakeItDownSubmissionV1.cumulativeRequestSnapshotHash`. Built from the SORTED
|
|
138
|
+
* supplied field codes + the normalized target key + the requester role so the same
|
|
139
|
+
* cumulative state always fingerprints identically (append-order independent).
|
|
140
|
+
*/
|
|
141
|
+
export function cumulativeSnapshotHash(args) {
|
|
142
|
+
const sorted = [...args.suppliedFieldCodes].sort();
|
|
143
|
+
return sha256Hex(['takeItDownSnapshot:v1', args.requesterRole, args.targetKey, sorted.join(',')].join(SEP));
|
|
144
|
+
}
|
|
145
|
+
// ===========================================================================
|
|
146
|
+
// Privacy-safe target summary (root + public projection — NO narrative / PII)
|
|
147
|
+
// ===========================================================================
|
|
148
|
+
/** A short, non-sensitive surface label per locator kind (no ids, no narrative). */
|
|
149
|
+
export function surfaceLabelFor(locator) {
|
|
150
|
+
switch (locator.kind) {
|
|
151
|
+
case 'mediaAsset':
|
|
152
|
+
return 'Media item';
|
|
153
|
+
case 'hallItem':
|
|
154
|
+
return 'Hall library item';
|
|
155
|
+
case 'squarePost':
|
|
156
|
+
return 'Square Streetz post';
|
|
157
|
+
case 'profileImage':
|
|
158
|
+
return 'Profile image';
|
|
159
|
+
case 'username':
|
|
160
|
+
return 'Username';
|
|
161
|
+
case 'craftSkill':
|
|
162
|
+
return 'Craft skill';
|
|
163
|
+
case 'commissionListing':
|
|
164
|
+
return 'Commission listing';
|
|
165
|
+
case 'audition':
|
|
166
|
+
return 'Audition';
|
|
167
|
+
case 'auditionEntry':
|
|
168
|
+
return 'Audition entry';
|
|
169
|
+
case 'guildInviteMessage':
|
|
170
|
+
return 'Guild invite message';
|
|
171
|
+
case 'chatAttachment':
|
|
172
|
+
return 'Chat attachment';
|
|
173
|
+
case 'guildChatMessage':
|
|
174
|
+
return 'Guild chat message';
|
|
175
|
+
case 'adminWorkMessage':
|
|
176
|
+
return 'Work correspondence message';
|
|
177
|
+
case 'commissionProposal':
|
|
178
|
+
return 'Commission proposal';
|
|
179
|
+
case 'workProject':
|
|
180
|
+
return 'Work project';
|
|
181
|
+
case 'workAsset':
|
|
182
|
+
return 'Work file';
|
|
183
|
+
case 'workRealm':
|
|
184
|
+
return 'Work realm';
|
|
185
|
+
case 'url':
|
|
186
|
+
return 'External link';
|
|
187
|
+
case 'additionalText':
|
|
188
|
+
return 'Described content';
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/** Build the privacy-safe `TargetLocatorSummaryV1` (kind + surface label +
|
|
192
|
+
* whether a TTT-hosted target was server-resolved). NEVER the narrative or ids. */
|
|
193
|
+
export function targetLocatorSummary(locator, hasResolvedTarget) {
|
|
194
|
+
return {
|
|
195
|
+
kind: locator.kind,
|
|
196
|
+
surfaceLabel: surfaceLabelFor(locator),
|
|
197
|
+
hasResolvedTarget,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/** TTT-hosted locator kinds the intake will synchronously server-resolve +
|
|
201
|
+
* snapshot + temp-hold. `url` / `additionalText` are external/unresolvable: store
|
|
202
|
+
* the locator + submission, invent NO target. */
|
|
203
|
+
const TTT_HOSTED_KINDS = new Set([
|
|
204
|
+
'mediaAsset',
|
|
205
|
+
'hallItem',
|
|
206
|
+
'squarePost',
|
|
207
|
+
'profileImage',
|
|
208
|
+
'username',
|
|
209
|
+
'craftSkill',
|
|
210
|
+
'commissionListing',
|
|
211
|
+
'audition',
|
|
212
|
+
'auditionEntry',
|
|
213
|
+
'guildInviteMessage',
|
|
214
|
+
'chatAttachment',
|
|
215
|
+
]);
|
|
216
|
+
/** True when the locator points at a TTT-hosted surface (server-resolvable). */
|
|
217
|
+
export function isTttHostedLocator(locator) {
|
|
218
|
+
return TTT_HOSTED_KINDS.has(locator.kind);
|
|
219
|
+
}
|
|
220
|
+
// The intake temp hold is placed on the canonical key(s) every destructive guard checks — the
|
|
221
|
+
// content-doc key (`contentDocResourceKey(docPath, 'current')` in `./resource-keys`) + the
|
|
222
|
+
// mediaAsset byte key when the target is media-backed. There is intentionally NO bespoke
|
|
223
|
+
// `nciiTemporaryTarget` key builder here: that namespace was consulted by NO guard, so a hold
|
|
224
|
+
// placed on it never blocked deletion ([H3] void). The route-side mirror's `contentDocCanonicalKey`
|
|
225
|
+
// is likewise NOT ported — it duplicated `contentDocResourceKey(docPath, 'current')`, which is the
|
|
226
|
+
// single key authority.
|
|
227
|
+
//# sourceMappingURL=ncii-intake-derivations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ncii-intake-derivations.js","sourceRoot":"","sources":["../../src/safety/ncii-intake-derivations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { MediaAsset, SafetyHoldResourceType } from '../doc-schemas/index.js';
|
|
2
|
+
/** A canonical resource key paired with its sha256 hash (the Firestore doc id). */
|
|
3
|
+
export interface ResourceKey {
|
|
4
|
+
/** The hold `resourceType` this key belongs to (Appendix A3 enum). */
|
|
5
|
+
readonly resourceType: SafetyHoldResourceType;
|
|
6
|
+
/** A natural identifier for the resource, stored on the ref as `resourceId`
|
|
7
|
+
* (human-debuggable; NOT used for hashing — the canonical key is). */
|
|
8
|
+
readonly resourceId: string;
|
|
9
|
+
/** The deterministic canonical key string (Appendix A3). */
|
|
10
|
+
readonly canonicalResourceKey: string;
|
|
11
|
+
/** `sha256(canonicalResourceKey)` hex — the `safetyHoldResources` doc id. */
|
|
12
|
+
readonly resourceKeyHash: string;
|
|
13
|
+
}
|
|
14
|
+
/** sha256-hex of a canonical key string. The single hashing chokepoint. */
|
|
15
|
+
export declare function resourceKeyHash(canonicalResourceKey: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Firestore content document target = document path + immutable revision.
|
|
18
|
+
* `docPath` must be the canonical full path (e.g. via `toPath(PATH_BUILDERS.x(...))`),
|
|
19
|
+
* NOT a client-supplied path. `revision` pins a mutable doc to a specific version so a
|
|
20
|
+
* post-hold edit cannot slip the bytes out from under the hold; pass the revision/
|
|
21
|
+
* version the report froze.
|
|
22
|
+
*/
|
|
23
|
+
export declare function contentDocResourceKey(docPath: string, revision: string | number): ResourceKey;
|
|
24
|
+
/**
|
|
25
|
+
* Storage object target = bucket + key + generation. `generation` pins the exact
|
|
26
|
+
* object version (a re-upload to the same key gets a new generation and is a different
|
|
27
|
+
* physical resource). Pass the generation captured when the hold was placed.
|
|
28
|
+
*/
|
|
29
|
+
export declare function storageObjectResourceKey(bucket: string, key: string, generation: string | number): ResourceKey;
|
|
30
|
+
/**
|
|
31
|
+
* Media target. Returns keys for BOTH:
|
|
32
|
+
* 1. the specific `mediaAssetId` (this exact asset/copy), AND
|
|
33
|
+
* 2. its `originLineage.rootIngestId` — when present — as a SEPARATE `mediaAsset`
|
|
34
|
+
* key so a hold can block the ENTIRE incident lineage (every copy/variant that
|
|
35
|
+
* inherited the same root ingest), per Appendix A0/A3 incident-wide blocking.
|
|
36
|
+
*
|
|
37
|
+
* The caller decides which key(s) to place a hold on: a single-asset takedown holds
|
|
38
|
+
* key[0]; an incident-wide block over a CSAM/NCII lineage holds the rootIngest key so
|
|
39
|
+
* every existing AND future copy of the same root is denied. Both keys are `mediaAsset`
|
|
40
|
+
* resourceType (rootIngest is a media identity, not a distinct type — A3 has no
|
|
41
|
+
* separate `rootIngest` type; it is modeled as a mediaAsset key over the root id).
|
|
42
|
+
*
|
|
43
|
+
* Order is stable: index 0 = the asset itself; index 1 (if any) = the rootIngest.
|
|
44
|
+
*/
|
|
45
|
+
export declare function mediaAssetResourceKeys(asset: Pick<MediaAsset, 'mediaAssetId' | 'originLineage'>): ResourceKey[];
|
|
46
|
+
/** The mediaAsset key for a bare rootIngestId (no asset doc in hand) — same canonical
|
|
47
|
+
* shape as `mediaAssetResourceKeys(...)`'s index-1 entry, so it hashes identically. */
|
|
48
|
+
export declare function rootIngestResourceKey(rootIngestId: string): ResourceKey;
|
|
49
|
+
/**
|
|
50
|
+
* Chat message-range target = channelId + a sequence/epoch boundary identifying the
|
|
51
|
+
* span of messages held. `messageSeqOrEpoch` is the caller's range identifier (e.g. a
|
|
52
|
+
* sequence number or epoch marker); the SAME range over the same channel must always
|
|
53
|
+
* be passed in the same canonical form by the caller.
|
|
54
|
+
*/
|
|
55
|
+
export declare function chatMessageRangeResourceKey(channelId: string, messageSeqOrEpoch: string | number): ResourceKey;
|
|
56
|
+
/** Channel target = channelId. */
|
|
57
|
+
export declare function channelResourceKey(channelId: string): ResourceKey;
|
|
58
|
+
/** Account target = uid. */
|
|
59
|
+
export declare function accountResourceKey(uid: string): ResourceKey;
|
|
60
|
+
//# sourceMappingURL=resource-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-keys.d.ts","sourceRoot":"","sources":["../../src/safety/resource-keys.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AASlF,mFAAmF;AACnF,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,YAAY,EAAE,sBAAsB,CAAC;IAC9C;2EACuE;IACvE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,oBAAoB,EAAE,MAAM,GAAG,MAAM,CAEpE;AAiBD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,CAE7F;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,GAAG,MAAM,GAC1B,WAAW,CAEb;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,cAAc,GAAG,eAAe,CAAC,GAAG,WAAW,EAAE,CAS/G;AAED;wFACwF;AACxF,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,WAAW,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,GAAG,MAAM,GACjC,WAAW,CAOb;AAED,kCAAkC;AAClC,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,CAEjE;AAED,4BAA4B;AAC5B,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAE3D"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// Canonical safety-hold resource keys (Trust & Safety IMPLEMENTATION_PLAN Appendix A3).
|
|
2
|
+
//
|
|
3
|
+
// A safety hold is keyed by the PHYSICAL resource it protects, not by the case or
|
|
4
|
+
// the request that created it. The `canonicalResourceKey` is a deterministic string
|
|
5
|
+
// built from exactly the identity fields that pin a physical resource:
|
|
6
|
+
//
|
|
7
|
+
// - a Firestore content target = document path + immutable revision/generation
|
|
8
|
+
// - a storage object = bucket + key + generation
|
|
9
|
+
// - a media target = mediaAsset identity (and, incident-wide, its
|
|
10
|
+
// MediaOriginLineageV1.rootIngestId)
|
|
11
|
+
// - a chat message range = channelId + sequence/epoch boundary
|
|
12
|
+
// - a channel = channelId
|
|
13
|
+
// - an account = uid
|
|
14
|
+
//
|
|
15
|
+
// `resourceKeyHash = sha256(canonicalResourceKey)` is the Firestore doc id for both
|
|
16
|
+
// `safetyHoldResources/{resourceKeyHash}` (the O(1) per-flag counter aggregate) and
|
|
17
|
+
// the `{caseId}__{resourceKeyHash}` ref. THE SAME PHYSICAL RESOURCE MUST ALWAYS HASH
|
|
18
|
+
// IDENTICALLY — that is the whole correctness story: every hold over the same bytes
|
|
19
|
+
// joins the same aggregate, and every destructive guard consults the same doc.
|
|
20
|
+
//
|
|
21
|
+
// This is the ONE canonical declaration (Rule 36). Both TTT app TS projects (the Cloud
|
|
22
|
+
// Functions graph AND the App Hosting route graph) import these builders from ttt-core
|
|
23
|
+
// rather than hand-mirroring the format — a re-key would otherwise drift the two runtimes
|
|
24
|
+
// apart. node:crypto sha256 keeps it pure + server-safe (this module lives behind the
|
|
25
|
+
// `./safety` entry, never on the main barrel, so the frontend bundle never loads it).
|
|
26
|
+
//
|
|
27
|
+
// Determinism rules (do not change without a key-version bump):
|
|
28
|
+
// - Format is `v1` + a type tag + the identity fields, joined by the unit-separator
|
|
29
|
+
// control char (\x1f), which cannot appear in a Firestore path, bucket name, key,
|
|
30
|
+
// uid, or channel id. No JSON (key ordering / whitespace is not load-bearing here;
|
|
31
|
+
// a flat separator-joined string is stable by construction).
|
|
32
|
+
// - The type tag prevents cross-type collisions (a contentDoc whose path happens to
|
|
33
|
+
// equal a storage key never shares a hash with that storage object).
|
|
34
|
+
// - A bump to the format string ('v1') is a hold-key migration and is NOT backward
|
|
35
|
+
// compatible — every existing ref/aggregate would re-key. Treat it as a breaking
|
|
36
|
+
// change to the entire hold authority.
|
|
37
|
+
import { createHash } from 'node:crypto';
|
|
38
|
+
/** Format/version tag for every canonical key. Bumping this re-keys ALL holds. */
|
|
39
|
+
const KEY_FORMAT = 'safetyHoldKey/v1';
|
|
40
|
+
/** Unit separator — illegal in every identity field we join, so it is an unambiguous
|
|
41
|
+
* field delimiter that never appears inside a path, key, uid, or channel id. */
|
|
42
|
+
const SEP = '\x1f';
|
|
43
|
+
/** sha256-hex of a canonical key string. The single hashing chokepoint. */
|
|
44
|
+
export function resourceKeyHash(canonicalResourceKey) {
|
|
45
|
+
return createHash('sha256').update(canonicalResourceKey, 'utf8').digest('hex');
|
|
46
|
+
}
|
|
47
|
+
/** Build a {canonicalResourceKey, resourceKeyHash} from a type tag + identity parts. */
|
|
48
|
+
function buildKey(resourceType, resourceId, ...parts) {
|
|
49
|
+
const canonicalResourceKey = [KEY_FORMAT, resourceType, ...parts].join(SEP);
|
|
50
|
+
return {
|
|
51
|
+
resourceType,
|
|
52
|
+
resourceId,
|
|
53
|
+
canonicalResourceKey,
|
|
54
|
+
resourceKeyHash: resourceKeyHash(canonicalResourceKey),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Firestore content document target = document path + immutable revision.
|
|
59
|
+
* `docPath` must be the canonical full path (e.g. via `toPath(PATH_BUILDERS.x(...))`),
|
|
60
|
+
* NOT a client-supplied path. `revision` pins a mutable doc to a specific version so a
|
|
61
|
+
* post-hold edit cannot slip the bytes out from under the hold; pass the revision/
|
|
62
|
+
* version the report froze.
|
|
63
|
+
*/
|
|
64
|
+
export function contentDocResourceKey(docPath, revision) {
|
|
65
|
+
return buildKey('contentDoc', docPath, docPath, String(revision));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Storage object target = bucket + key + generation. `generation` pins the exact
|
|
69
|
+
* object version (a re-upload to the same key gets a new generation and is a different
|
|
70
|
+
* physical resource). Pass the generation captured when the hold was placed.
|
|
71
|
+
*/
|
|
72
|
+
export function storageObjectResourceKey(bucket, key, generation) {
|
|
73
|
+
return buildKey('storageObject', `${bucket}/${key}`, bucket, key, String(generation));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Media target. Returns keys for BOTH:
|
|
77
|
+
* 1. the specific `mediaAssetId` (this exact asset/copy), AND
|
|
78
|
+
* 2. its `originLineage.rootIngestId` — when present — as a SEPARATE `mediaAsset`
|
|
79
|
+
* key so a hold can block the ENTIRE incident lineage (every copy/variant that
|
|
80
|
+
* inherited the same root ingest), per Appendix A0/A3 incident-wide blocking.
|
|
81
|
+
*
|
|
82
|
+
* The caller decides which key(s) to place a hold on: a single-asset takedown holds
|
|
83
|
+
* key[0]; an incident-wide block over a CSAM/NCII lineage holds the rootIngest key so
|
|
84
|
+
* every existing AND future copy of the same root is denied. Both keys are `mediaAsset`
|
|
85
|
+
* resourceType (rootIngest is a media identity, not a distinct type — A3 has no
|
|
86
|
+
* separate `rootIngest` type; it is modeled as a mediaAsset key over the root id).
|
|
87
|
+
*
|
|
88
|
+
* Order is stable: index 0 = the asset itself; index 1 (if any) = the rootIngest.
|
|
89
|
+
*/
|
|
90
|
+
export function mediaAssetResourceKeys(asset) {
|
|
91
|
+
const keys = [
|
|
92
|
+
buildKey('mediaAsset', asset.mediaAssetId, 'asset', asset.mediaAssetId),
|
|
93
|
+
];
|
|
94
|
+
const rootIngestId = asset.originLineage?.rootIngestId;
|
|
95
|
+
if (rootIngestId) {
|
|
96
|
+
keys.push(buildKey('mediaAsset', rootIngestId, 'rootIngest', rootIngestId));
|
|
97
|
+
}
|
|
98
|
+
return keys;
|
|
99
|
+
}
|
|
100
|
+
/** The mediaAsset key for a bare rootIngestId (no asset doc in hand) — same canonical
|
|
101
|
+
* shape as `mediaAssetResourceKeys(...)`'s index-1 entry, so it hashes identically. */
|
|
102
|
+
export function rootIngestResourceKey(rootIngestId) {
|
|
103
|
+
return buildKey('mediaAsset', rootIngestId, 'rootIngest', rootIngestId);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Chat message-range target = channelId + a sequence/epoch boundary identifying the
|
|
107
|
+
* span of messages held. `messageSeqOrEpoch` is the caller's range identifier (e.g. a
|
|
108
|
+
* sequence number or epoch marker); the SAME range over the same channel must always
|
|
109
|
+
* be passed in the same canonical form by the caller.
|
|
110
|
+
*/
|
|
111
|
+
export function chatMessageRangeResourceKey(channelId, messageSeqOrEpoch) {
|
|
112
|
+
return buildKey('chatMessageRange', `${channelId}#${messageSeqOrEpoch}`, channelId, String(messageSeqOrEpoch));
|
|
113
|
+
}
|
|
114
|
+
/** Channel target = channelId. */
|
|
115
|
+
export function channelResourceKey(channelId) {
|
|
116
|
+
return buildKey('channel', channelId, channelId);
|
|
117
|
+
}
|
|
118
|
+
/** Account target = uid. */
|
|
119
|
+
export function accountResourceKey(uid) {
|
|
120
|
+
return buildKey('account', uid, uid);
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=resource-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-keys.js","sourceRoot":"","sources":["../../src/safety/resource-keys.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,4 +22,8 @@ export declare const UpdateGuildInviteStakeSharesInputSchema: z.ZodObject<{
|
|
|
22
22
|
newStakeShares: z.ZodNumber;
|
|
23
23
|
}, z.core.$strict>;
|
|
24
24
|
export type UpdateGuildInviteStakeSharesInput = z.infer<typeof UpdateGuildInviteStakeSharesInputSchema>;
|
|
25
|
+
export declare const DeleteAdminDispatchInputSchema: z.ZodObject<{
|
|
26
|
+
adminDispatchId: z.ZodString;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
export type DeleteAdminDispatchInput = z.infer<typeof DeleteAdminDispatchInputSchema>;
|
|
25
29
|
//# sourceMappingURL=admin-dispatch-actions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-dispatch-actions.d.ts","sourceRoot":"","sources":["../../src/schemas/admin-dispatch-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,oCAAoC;;;;;;kBAGtC,CAAC;AACZ,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAC;AAElG,eAAO,MAAM,mCAAmC;;;;;;;;kBAGrC,CAAC;AACZ,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC;AAEhG,eAAO,MAAM,uCAAuC;;;kBAGzC,CAAC;AACZ,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uCAAuC,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"admin-dispatch-actions.d.ts","sourceRoot":"","sources":["../../src/schemas/admin-dispatch-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,oCAAoC;;;;;;kBAGtC,CAAC;AACZ,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAC;AAElG,eAAO,MAAM,mCAAmC;;;;;;;;kBAGrC,CAAC;AACZ,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC;AAEhG,eAAO,MAAM,uCAAuC;;;kBAGzC,CAAC;AACZ,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uCAAuC,CAAC,CAAC;AAIxG,eAAO,MAAM,8BAA8B;;iBAEzC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC"}
|
|
@@ -14,4 +14,9 @@ export const UpdateGuildInviteStakeSharesInputSchema = z.object({
|
|
|
14
14
|
guildInviteId: guildInviteIdSchema,
|
|
15
15
|
newStakeShares: z.number().int().min(1),
|
|
16
16
|
}).strict();
|
|
17
|
+
// Admin/jr-admin deletes a user's support dispatch thread (`deleteAdminDispatch`). Non-strict
|
|
18
|
+
// posture is carried faithfully from the source callable.
|
|
19
|
+
export const DeleteAdminDispatchInputSchema = z.object({
|
|
20
|
+
adminDispatchId: adminDispatchIdSchema,
|
|
21
|
+
});
|
|
17
22
|
//# sourceMappingURL=admin-dispatch-actions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-dispatch-actions.js","sourceRoot":"","sources":["../../src/schemas/admin-dispatch-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAExE,0FAA0F;AAC1F,6FAA6F;AAC7F,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3D,eAAe,EAAE,qBAAqB;IACtC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;CAC5D,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1D,aAAa,EAAE,mBAAmB;IAClC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;CAC1D,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,uCAAuC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9D,aAAa,EAAE,mBAAmB;IAClC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACxC,CAAC,CAAC,MAAM,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"admin-dispatch-actions.js","sourceRoot":"","sources":["../../src/schemas/admin-dispatch-actions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAExE,0FAA0F;AAC1F,6FAA6F;AAC7F,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3D,eAAe,EAAE,qBAAqB;IACtC,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAAC;CAC5D,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1D,aAAa,EAAE,mBAAmB;IAClC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;CAC1D,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,uCAAuC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9D,aAAa,EAAE,mBAAmB;IAClC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACxC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,8FAA8F;AAC9F,0DAA0D;AAC1D,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IACrD,eAAe,EAAE,qBAAqB;CACvC,CAAC,CAAC"}
|
package/dist/schemas/admin.d.ts
CHANGED
|
@@ -179,6 +179,83 @@ export declare const RequireRetitleInputSchema: z.ZodObject<{
|
|
|
179
179
|
reason: z.ZodString;
|
|
180
180
|
}, z.core.$strict>;
|
|
181
181
|
export type RequireRetitleInput = z.infer<typeof RequireRetitleInputSchema>;
|
|
182
|
+
declare const ModerationShellClearFieldSchema: z.ZodEnum<{
|
|
183
|
+
workingTitle: "workingTitle";
|
|
184
|
+
workingDescription: "workingDescription";
|
|
185
|
+
}>;
|
|
186
|
+
export type ModerationShellClearField = z.infer<typeof ModerationShellClearFieldSchema>;
|
|
187
|
+
export declare const ClearWorkProjectTextInputSchema: z.ZodObject<{
|
|
188
|
+
workProjectId: z.ZodString;
|
|
189
|
+
fields: z.ZodArray<z.ZodEnum<{
|
|
190
|
+
workingTitle: "workingTitle";
|
|
191
|
+
workingDescription: "workingDescription";
|
|
192
|
+
}>>;
|
|
193
|
+
reason: z.ZodString;
|
|
194
|
+
}, z.core.$strict>;
|
|
195
|
+
export type ClearWorkProjectTextInput = z.infer<typeof ClearWorkProjectTextInputSchema>;
|
|
196
|
+
export declare const ClearWorkRealmTextInputSchema: z.ZodObject<{
|
|
197
|
+
workRealmId: z.ZodString;
|
|
198
|
+
fields: z.ZodArray<z.ZodEnum<{
|
|
199
|
+
workingTitle: "workingTitle";
|
|
200
|
+
workingDescription: "workingDescription";
|
|
201
|
+
}>>;
|
|
202
|
+
reason: z.ZodString;
|
|
203
|
+
}, z.core.$strict>;
|
|
204
|
+
export type ClearWorkRealmTextInput = z.infer<typeof ClearWorkRealmTextInputSchema>;
|
|
205
|
+
declare const HallClearFieldSchema: z.ZodEnum<{
|
|
206
|
+
title: "title";
|
|
207
|
+
description: "description";
|
|
208
|
+
content: "content";
|
|
209
|
+
}>;
|
|
210
|
+
export type HallClearField = z.infer<typeof HallClearFieldSchema>;
|
|
211
|
+
export declare const ClearHallContentTextInputSchema: z.ZodObject<{
|
|
212
|
+
hallItemId: z.ZodString;
|
|
213
|
+
workProjectType: z.ZodEnum<{
|
|
214
|
+
Tales: "Tales";
|
|
215
|
+
Tunes: "Tunes";
|
|
216
|
+
Television: "Television";
|
|
217
|
+
}>;
|
|
218
|
+
subItemId: z.ZodOptional<z.ZodString>;
|
|
219
|
+
fields: z.ZodArray<z.ZodEnum<{
|
|
220
|
+
title: "title";
|
|
221
|
+
description: "description";
|
|
222
|
+
content: "content";
|
|
223
|
+
}>>;
|
|
224
|
+
reason: z.ZodString;
|
|
225
|
+
}, z.core.$strict>;
|
|
226
|
+
export type ClearHallContentTextInput = z.infer<typeof ClearHallContentTextInputSchema>;
|
|
227
|
+
export declare const GetLatestHideCascadeInputSchema: z.ZodObject<{
|
|
228
|
+
entityId: z.ZodString;
|
|
229
|
+
targetType: z.ZodEnum<{
|
|
230
|
+
"work-project": "work-project";
|
|
231
|
+
"work-realm": "work-realm";
|
|
232
|
+
}>;
|
|
233
|
+
}, z.core.$strict>;
|
|
234
|
+
export type GetLatestHideCascadeInput = z.infer<typeof GetLatestHideCascadeInputSchema>;
|
|
235
|
+
export declare const ModerateReportedContentInputSchema: z.ZodObject<{
|
|
236
|
+
reportGroupId: z.ZodString;
|
|
237
|
+
targetType: z.ZodEnum<{
|
|
238
|
+
"craft-skill": "craft-skill";
|
|
239
|
+
"commission-listing": "commission-listing";
|
|
240
|
+
"commission-proposal": "commission-proposal";
|
|
241
|
+
"square-streetz-post": "square-streetz-post";
|
|
242
|
+
"profile-picture": "profile-picture";
|
|
243
|
+
"admin-work-message": "admin-work-message";
|
|
244
|
+
"hall-library-item": "hall-library-item";
|
|
245
|
+
audition: "audition";
|
|
246
|
+
"audition-entry": "audition-entry";
|
|
247
|
+
"work-asset": "work-asset";
|
|
248
|
+
}>;
|
|
249
|
+
reportedItemId: z.ZodString;
|
|
250
|
+
parentItemId: z.ZodOptional<z.ZodString>;
|
|
251
|
+
action: z.ZodEnum<{
|
|
252
|
+
remove: "remove";
|
|
253
|
+
hide: "hide";
|
|
254
|
+
restore: "restore";
|
|
255
|
+
}>;
|
|
256
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
257
|
+
}, z.core.$strict>;
|
|
258
|
+
export type ModerateReportedContentInput = z.infer<typeof ModerateReportedContentInputSchema>;
|
|
182
259
|
export declare const StagedActionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
183
260
|
button: z.ZodEnum<{
|
|
184
261
|
hideContent: "hideContent";
|
|
@@ -489,4 +566,5 @@ export declare const GetDeadLettersInputSchema: z.ZodOptional<z.ZodNullable<z.Zo
|
|
|
489
566
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
490
567
|
}, z.core.$strict>>>;
|
|
491
568
|
export type GetDeadLettersInput = z.infer<typeof GetDeadLettersInputSchema>;
|
|
569
|
+
export {};
|
|
492
570
|
//# sourceMappingURL=admin.d.ts.map
|