@ttt-productions/ttt-core 0.79.60 → 0.79.61
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/index.d.ts +2 -0
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +2 -0
- package/dist/constants/index.js.map +1 -1
- package/dist/constants/pagination.d.ts +2 -0
- package/dist/constants/pagination.d.ts.map +1 -1
- package/dist/constants/pagination.js +2 -0
- package/dist/constants/pagination.js.map +1 -1
- package/dist/constants/safety-active-statuses.d.ts +23 -0
- package/dist/constants/safety-active-statuses.d.ts.map +1 -0
- package/dist/constants/safety-active-statuses.js +56 -0
- package/dist/constants/safety-active-statuses.js.map +1 -0
- package/dist/constants/scheduled-jobs.d.ts +1 -1
- package/dist/constants/scheduled-jobs.d.ts.map +1 -1
- package/dist/constants/scheduled-jobs.js +3 -0
- package/dist/constants/scheduled-jobs.js.map +1 -1
- package/dist/constants/telemetry-content-policy.d.ts +9 -0
- package/dist/constants/telemetry-content-policy.d.ts.map +1 -0
- package/dist/constants/telemetry-content-policy.js +49 -0
- package/dist/constants/telemetry-content-policy.js.map +1 -0
- package/dist/doc-schemas/backend-state.d.ts +3 -0
- package/dist/doc-schemas/backend-state.d.ts.map +1 -1
- package/dist/doc-schemas/payments.d.ts +25 -0
- package/dist/doc-schemas/payments.d.ts.map +1 -1
- package/dist/doc-schemas/payments.js +32 -0
- package/dist/doc-schemas/payments.js.map +1 -1
- package/dist/doc-schemas/registry.d.ts +1 -0
- package/dist/doc-schemas/registry.d.ts.map +1 -1
- package/dist/schemas/payments.d.ts +3 -4
- package/dist/schemas/payments.d.ts.map +1 -1
- package/dist/schemas/payments.js +10 -8
- package/dist/schemas/payments.js.map +1 -1
- package/dist/schemas/safety.d.ts +99 -0
- package/dist/schemas/safety.d.ts.map +1 -1
- package/dist/schemas/safety.js +31 -3
- package/dist/schemas/safety.js.map +1 -1
- package/dist/schemas/work-project-management.d.ts +41 -0
- package/dist/schemas/work-project-management.d.ts.map +1 -1
- package/dist/schemas/work-project-management.js +14 -0
- package/dist/schemas/work-project-management.js.map +1 -1
- package/dist/types/audit.d.ts +1 -1
- package/dist/types/audit.d.ts.map +1 -1
- package/dist/types/audit.js.map +1 -1
- package/package.json +1 -1
|
@@ -14,6 +14,8 @@ export * from './legal-review-notice-state.js';
|
|
|
14
14
|
export * from './legal-review-notice.js';
|
|
15
15
|
export * from './safety-confirmation-phrases.js';
|
|
16
16
|
export * from './safety-telemetry-patterns.js';
|
|
17
|
+
export * from './safety-active-statuses.js';
|
|
18
|
+
export * from './telemetry-content-policy.js';
|
|
17
19
|
export * from './pagination.js';
|
|
18
20
|
export * from './release-flags.js';
|
|
19
21
|
export * from './retention.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
|
package/dist/constants/index.js
CHANGED
|
@@ -14,6 +14,8 @@ export * from './legal-review-notice-state.js';
|
|
|
14
14
|
export * from './legal-review-notice.js';
|
|
15
15
|
export * from './safety-confirmation-phrases.js';
|
|
16
16
|
export * from './safety-telemetry-patterns.js';
|
|
17
|
+
export * from './safety-active-statuses.js';
|
|
18
|
+
export * from './telemetry-content-policy.js';
|
|
17
19
|
export * from './pagination.js';
|
|
18
20
|
export * from './release-flags.js';
|
|
19
21
|
export * from './retention.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC","sourcesContent":["export * from './analytics.js';\nexport * from './app-mode.js';\nexport * from './business.js';\nexport * from './chat.js';\nexport * from './conversation-files.js';\nexport * from './moderation.js';\nexport * from './options.js';\nexport * from './admin-labels.js';\nexport * from './craft-skill-statements.js';\nexport * from './publish-attestations.js';\nexport * from './pledge-and-bouquet-copy.js';\nexport * from './public-documents.js';\nexport * from './legal-review-notice-state.js';\nexport * from './legal-review-notice.js';\nexport * from './safety-confirmation-phrases.js';\nexport * from './safety-telemetry-patterns.js';\nexport * from './pagination.js';\nexport * from './release-flags.js';\nexport * from './retention.js';\nexport * from './scheduled-jobs.js';\nexport * from './media-download.js';\nexport * from './media-processing.js';\nexport * from './storage-keys.js';\nexport * from './company-mascots.js';\nexport * from './center-stage-rooms.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC","sourcesContent":["export * from './analytics.js';\nexport * from './app-mode.js';\nexport * from './business.js';\nexport * from './chat.js';\nexport * from './conversation-files.js';\nexport * from './moderation.js';\nexport * from './options.js';\nexport * from './admin-labels.js';\nexport * from './craft-skill-statements.js';\nexport * from './publish-attestations.js';\nexport * from './pledge-and-bouquet-copy.js';\nexport * from './public-documents.js';\nexport * from './legal-review-notice-state.js';\nexport * from './legal-review-notice.js';\nexport * from './safety-confirmation-phrases.js';\nexport * from './safety-telemetry-patterns.js';\nexport * from './safety-active-statuses.js';\nexport * from './telemetry-content-policy.js';\nexport * from './pagination.js';\nexport * from './release-flags.js';\nexport * from './retention.js';\nexport * from './scheduled-jobs.js';\nexport * from './media-download.js';\nexport * from './media-processing.js';\nexport * from './storage-keys.js';\nexport * from './company-mascots.js';\nexport * from './center-stage-rooms.js';\n"]}
|
|
@@ -13,6 +13,8 @@ export declare const ITEMS_PER_PAGE_TELEVISION_EPISODES = 3;
|
|
|
13
13
|
export declare const ITEMS_PER_PAGE_PROPOSAL_ARTISANS = 5;
|
|
14
14
|
export declare const ITEMS_PER_PAGE_FOLLOWED_USERS = 10;
|
|
15
15
|
export declare const ITEMS_PER_PAGE_ADMIN_DISPATCH_THREADS = 10;
|
|
16
|
+
/** The admin Dispatches browse list (every support thread, admin-only) — not a member's own thread list above. */
|
|
17
|
+
export declare const ITEMS_PER_PAGE_ADMIN_DISPATCH_BROWSE = 12;
|
|
16
18
|
/** Page size for the pledge-payments list hook. */
|
|
17
19
|
export declare const PLEDGE_PAYMENTS_PER_PAGE = 20;
|
|
18
20
|
/** Page size for the pending-media archive list hook. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/constants/pagination.ts"],"names":[],"mappings":"AAGA,0DAA0D;AAC1D,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,sCAAsC,IAAI,CAAC;AACxD,eAAO,MAAM,+BAA+B,IAAI,CAAC;AACjD,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,kCAAkC,IAAI,CAAC;AACpD,eAAO,MAAM,uCAAuC,IAAI,CAAC;AACzD,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAC5C,eAAO,MAAM,kCAAkC,IAAI,CAAC;AACpD,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAClD,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,qCAAqC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/constants/pagination.ts"],"names":[],"mappings":"AAGA,0DAA0D;AAC1D,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,sCAAsC,IAAI,CAAC;AACxD,eAAO,MAAM,+BAA+B,IAAI,CAAC;AACjD,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,kCAAkC,IAAI,CAAC;AACpD,eAAO,MAAM,uCAAuC,IAAI,CAAC;AACzD,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAC5C,eAAO,MAAM,kCAAkC,IAAI,CAAC;AACpD,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAClD,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,qCAAqC,KAAK,CAAC;AACxD,kHAAkH;AAClH,eAAO,MAAM,oCAAoC,KAAK,CAAC;AAIvD,mDAAmD;AACnD,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAE3C,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,0CAA0C;AAC1C,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC,qDAAqD;AACrD,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,gDAAgD;AAChD,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C,8GAA8G;AAC9G,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,KAAK,CAAC;AAExD,4GAA4G;AAC5G,eAAO,MAAM,2BAA2B,QAAiD,CAAC;AAI1F,uGAAuG;AACvG,eAAO,MAAM,2BAA2B;;;;;CAK9B,CAAC"}
|
|
@@ -15,6 +15,8 @@ export const ITEMS_PER_PAGE_TELEVISION_EPISODES = 3;
|
|
|
15
15
|
export const ITEMS_PER_PAGE_PROPOSAL_ARTISANS = 5;
|
|
16
16
|
export const ITEMS_PER_PAGE_FOLLOWED_USERS = 10;
|
|
17
17
|
export const ITEMS_PER_PAGE_ADMIN_DISPATCH_THREADS = 10;
|
|
18
|
+
/** The admin Dispatches browse list (every support thread, admin-only) — not a member's own thread list above. */
|
|
19
|
+
export const ITEMS_PER_PAGE_ADMIN_DISPATCH_BROWSE = 12;
|
|
18
20
|
// --- Hook-specific page sizes ---
|
|
19
21
|
/** Page size for the pledge-payments list hook. */
|
|
20
22
|
export const PLEDGE_PAYMENTS_PER_PAGE = 20;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/constants/pagination.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,0DAA0D;AAC1D,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,sCAAsC,GAAG,CAAC,CAAC;AACxD,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC;AACjD,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAC/C,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,uCAAuC,GAAG,CAAC,CAAC;AACzD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAC5C,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAChD,MAAM,CAAC,MAAM,qCAAqC,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/constants/pagination.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,0DAA0D;AAC1D,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,sCAAsC,GAAG,CAAC,CAAC;AACxD,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC;AACjD,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAC/C,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,uCAAuC,GAAG,CAAC,CAAC;AACzD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAC5C,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAChD,MAAM,CAAC,MAAM,qCAAqC,GAAG,EAAE,CAAC;AACxD,kHAAkH;AAClH,MAAM,CAAC,MAAM,oCAAoC,GAAG,EAAE,CAAC;AAEvD,mCAAmC;AAEnC,mDAAmD;AACnD,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAEnC,wDAAwD;AACxD,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAEpC,0CAA0C;AAC1C,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AAEjC,qDAAqD;AACrD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC,gDAAgD;AAChD,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAE7C,8GAA8G;AAC9G,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,qCAAqC,GAAG,EAAE,CAAC;AAExD,4GAA4G;AAC5G,MAAM,CAAC,MAAM,2BAA2B,GAAG,aAAa,CAAC,OAAO,CAAC,wBAAwB,CAAC;AAE1F,mCAAmC;AAEnC,uGAAuG;AACvG,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,cAAc,EAAE,EAAE;IAClB,gBAAgB,EAAE,EAAE;IACpB,iBAAiB,EAAE,EAAE;IACrB,kBAAkB,EAAE,GAAG;CACf,CAAC","sourcesContent":["// Pagination page sizes and hallLibrary UX constants.\nimport { ACTIVE_LIMITS } from './app-mode.js';\n\n/** Default pagination size when no other size applies. */\nexport const ITEMS_PER_PAGE_GENERAL = 5;\n\nexport const ITEMS_PER_PAGE_MESSAGES = 5;\nexport const ITEMS_PER_PAGE_ADMIN_DISPATCH_MESSAGES = 6;\nexport const ITEMS_PER_PAGE_COMMISSION_BOARD = 5;\nexport const ITEMS_PER_PAGE_GUILDMATE_USERS = 3;\nexport const ITEMS_PER_PAGE_GUILD_INVITES = 10;\nexport const ITEMS_PER_PAGE_OWNED_WORK_PROJECTS = 3;\nexport const ITEMS_PER_PAGE_ASSOCIATED_WORK_PROJECTS = 3;\nexport const ITEMS_PER_PAGE_CHAPTERS = 5;\nexport const ITEMS_PER_PAGE_TUNE_TRACKS = 3;\nexport const ITEMS_PER_PAGE_TELEVISION_EPISODES = 3;\nexport const ITEMS_PER_PAGE_PROPOSAL_ARTISANS = 5;\nexport const ITEMS_PER_PAGE_FOLLOWED_USERS = 10;\nexport const ITEMS_PER_PAGE_ADMIN_DISPATCH_THREADS = 10;\n/** The admin Dispatches browse list (every support thread, admin-only) — not a member's own thread list above. */\nexport const ITEMS_PER_PAGE_ADMIN_DISPATCH_BROWSE = 12;\n\n// --- Hook-specific page sizes ---\n\n/** Page size for the pledge-payments list hook. */\nexport const PLEDGE_PAYMENTS_PER_PAGE = 20;\n\n/** Page size for the pending-media archive list hook. */\nexport const ARCHIVE_PER_PAGE = 10;\n\n/** Page size for the workProject-channels list hook. */\nexport const CHANNELS_PER_PAGE = 10;\n\n/** Page size for the social feed hook. */\nexport const POSTS_PER_PAGE = 20;\n\n/** Page size for the content-violation list hook. */\nexport const VIOLATIONS_PER_PAGE = 5;\n\n/** Page size for the craft-skills list hook. */\nexport const CRAFT_SKILL_MEDIA_PER_PAGE = 12;\n\n/** Page size for each Works list on a Realm's page (canon and non-canon), a card grid like the craft list. */\nexport const ITEMS_PER_PAGE_REALM_WORKS = 12;\n\n/**\n * Hard page limit for the Realm shared-files gallery projection (`getRealmSharedFiles`).\n * The query was previously unbounded; this is the named cap the input schema derives its\n * `limit` bound from and the server clamps to, so one Realm's pool can never be read (or\n * requested) in a single unbounded page. Matches the card-grid rhythm of the gallery.\n */\nexport const REALM_SHARED_FILES_PAGE_LIMIT = 24;\n\n/**\n * Hard page limit for the steward/admin realm-file promotion queue\n * (`getRealmFilePromotionQueue`). Smaller than the gallery page: the queue is a decision\n * surface a steward works through, not a browse grid.\n */\nexport const REALM_FILE_PROMOTION_QUEUE_PAGE_LIMIT = 20;\n\n/** Maximum number of recent posts the trending-feed scheduled commission processes per run. Mode-varied. */\nexport const TRENDING_FEED_PROCESS_LIMIT = ACTIVE_LIMITS.batches.trendingFeedProcessLimit;\n\n// --- HallLibrary UX constants ---\n\n/** HallLibrary page-level UX values (page size, recency window, search debounce, per-item tag cap). */\nexport const HALL_LIBRARY_PAGE_CONSTANTS = {\n ITEMS_PER_PAGE: 20,\n MAX_RECENT_VIEWS: 50,\n MAX_TAGS_PER_ITEM: 10,\n SEARCH_DEBOUNCE_MS: 300,\n} as const;\n\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ChildSafetyWorkStatus, SafetyCaseLane } from '../doc-schemas/safety/case.js';
|
|
2
|
+
import type { NciiInternalStatus, TakeItDownPublicStatus } from '../doc-schemas/safety/foundation.js';
|
|
3
|
+
/** Child-safety case work statuses still open (the `workStatus` an active-case query matches). */
|
|
4
|
+
export declare const CHILD_SAFETY_ACTIVE_WORK_STATUSES: readonly ChildSafetyWorkStatus[];
|
|
5
|
+
/** NCII case statuses still open (the `internalStatus` an active-case query matches). */
|
|
6
|
+
export declare const NCII_ACTIVE_INTERNAL_STATUSES: readonly NciiInternalStatus[];
|
|
7
|
+
/** Take-it-down request statuses still open (the `publicStatus` an active-request query matches). */
|
|
8
|
+
export declare const TAKE_IT_DOWN_ACTIVE_PUBLIC_STATUSES: readonly TakeItDownPublicStatus[];
|
|
9
|
+
declare const STATUS_IS_ACTIVE_BY_LANE: {
|
|
10
|
+
csam: Record<"processing" | "failed" | "new" | "triaged" | "reporting" | "actioning" | "operationallyResolved", boolean>;
|
|
11
|
+
ncii: Record<"processing" | "failed" | "rejected" | "removed" | "open" | "removalInProgress" | "closed", boolean>;
|
|
12
|
+
};
|
|
13
|
+
/** A safety case's lane and its status in that lane's own status set. */
|
|
14
|
+
export type SafetyCaseStatusRef = {
|
|
15
|
+
[Lane in SafetyCaseLane]: {
|
|
16
|
+
caseType: Lane;
|
|
17
|
+
status: keyof (typeof STATUS_IS_ACTIVE_BY_LANE)[Lane];
|
|
18
|
+
};
|
|
19
|
+
}[SafetyCaseLane];
|
|
20
|
+
/** Whether a safety case is still open work, read from its own lane's status set. */
|
|
21
|
+
export declare function isActiveSafetyCaseStatus(ref: SafetyCaseStatusRef): boolean;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=safety-active-statuses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety-active-statuses.d.ts","sourceRoot":"","sources":["../../src/constants/safety-active-statuses.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC3F,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAmCtG,kGAAkG;AAClG,eAAO,MAAM,iCAAiC,EAAE,SAAS,qBAAqB,EAE7E,CAAC;AAEF,yFAAyF;AACzF,eAAO,MAAM,6BAA6B,EAAE,SAAS,kBAAkB,EAAqD,CAAC;AAE7H,qGAAqG;AACrG,eAAO,MAAM,mCAAmC,EAAE,SAAS,sBAAsB,EAEhF,CAAC;AAIF,QAAA,MAAM,wBAAwB;;;CAG6B,CAAC;AAE5D,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG;KAC/B,IAAI,IAAI,cAAc,GAAG;QAAE,QAAQ,EAAE,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC,IAAI,CAAC,CAAA;KAAE;CACpG,CAAC,cAAc,CAAC,CAAC;AAElB,qFAAqF;AACrF,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAG1E"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Which safety-case and take-it-down statuses are still open work. The Safety Case Console's
|
|
2
|
+
// active lists, the ops snapshot's Legal-Clocks counts, and the closed-case lookup's reopen check
|
|
3
|
+
// all read these, so the console an operator clicks through to and the count that sent them
|
|
4
|
+
// there always agree. A case stays active until its worker verifies a terminal status: a close in
|
|
5
|
+
// progress (`processing`) and a worker out of retries (`failed`) are still open work.
|
|
6
|
+
//
|
|
7
|
+
// Each status is classified in a map over its whole union, so a new status does not build until
|
|
8
|
+
// it is placed. Type-only imports keep this module free of runtime dependencies for the backend
|
|
9
|
+
// bundles that load it.
|
|
10
|
+
const CHILD_SAFETY_WORK_STATUS_IS_ACTIVE = {
|
|
11
|
+
new: true,
|
|
12
|
+
triaged: true,
|
|
13
|
+
reporting: true,
|
|
14
|
+
actioning: true,
|
|
15
|
+
processing: true,
|
|
16
|
+
failed: true,
|
|
17
|
+
operationallyResolved: false,
|
|
18
|
+
};
|
|
19
|
+
const NCII_INTERNAL_STATUS_IS_ACTIVE = {
|
|
20
|
+
open: true,
|
|
21
|
+
removalInProgress: true,
|
|
22
|
+
processing: true,
|
|
23
|
+
failed: true,
|
|
24
|
+
removed: false,
|
|
25
|
+
rejected: false,
|
|
26
|
+
closed: false,
|
|
27
|
+
};
|
|
28
|
+
const TAKE_IT_DOWN_PUBLIC_STATUS_IS_ACTIVE = {
|
|
29
|
+
received: true,
|
|
30
|
+
needsMoreInfo: true,
|
|
31
|
+
validInProgress: true,
|
|
32
|
+
completed: false,
|
|
33
|
+
unableToLocate: false,
|
|
34
|
+
invalidGeneralReason: false,
|
|
35
|
+
};
|
|
36
|
+
function activeStatusesOf(isActive) {
|
|
37
|
+
return Object.keys(isActive).filter((status) => isActive[status]);
|
|
38
|
+
}
|
|
39
|
+
/** Child-safety case work statuses still open (the `workStatus` an active-case query matches). */
|
|
40
|
+
export const CHILD_SAFETY_ACTIVE_WORK_STATUSES = activeStatusesOf(CHILD_SAFETY_WORK_STATUS_IS_ACTIVE);
|
|
41
|
+
/** NCII case statuses still open (the `internalStatus` an active-case query matches). */
|
|
42
|
+
export const NCII_ACTIVE_INTERNAL_STATUSES = activeStatusesOf(NCII_INTERNAL_STATUS_IS_ACTIVE);
|
|
43
|
+
/** Take-it-down request statuses still open (the `publicStatus` an active-request query matches). */
|
|
44
|
+
export const TAKE_IT_DOWN_ACTIVE_PUBLIC_STATUSES = activeStatusesOf(TAKE_IT_DOWN_PUBLIC_STATUS_IS_ACTIVE);
|
|
45
|
+
// Keyed by the canonical lane union: a lane added to or renamed in SafetyCaseLaneSchema does not
|
|
46
|
+
// build until its status set is placed here.
|
|
47
|
+
const STATUS_IS_ACTIVE_BY_LANE = {
|
|
48
|
+
csam: CHILD_SAFETY_WORK_STATUS_IS_ACTIVE,
|
|
49
|
+
ncii: NCII_INTERNAL_STATUS_IS_ACTIVE,
|
|
50
|
+
};
|
|
51
|
+
/** Whether a safety case is still open work, read from its own lane's status set. */
|
|
52
|
+
export function isActiveSafetyCaseStatus(ref) {
|
|
53
|
+
const isActive = STATUS_IS_ACTIVE_BY_LANE[ref.caseType];
|
|
54
|
+
return isActive[ref.status] === true;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=safety-active-statuses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety-active-statuses.js","sourceRoot":"","sources":["../../src/constants/safety-active-statuses.ts"],"names":[],"mappings":"AAAA,6FAA6F;AAC7F,kGAAkG;AAClG,4FAA4F;AAC5F,kGAAkG;AAClG,sFAAsF;AACtF,EAAE;AACF,gGAAgG;AAChG,gGAAgG;AAChG,wBAAwB;AAKxB,MAAM,kCAAkC,GAA2C;IACjF,GAAG,EAAE,IAAI;IACT,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,IAAI;IACZ,qBAAqB,EAAE,KAAK;CAC7B,CAAC;AAEF,MAAM,8BAA8B,GAAwC;IAC1E,IAAI,EAAE,IAAI;IACV,iBAAiB,EAAE,IAAI;IACvB,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,KAAK;IACf,MAAM,EAAE,KAAK;CACd,CAAC;AAEF,MAAM,oCAAoC,GAA4C;IACpF,QAAQ,EAAE,IAAI;IACd,aAAa,EAAE,IAAI;IACnB,eAAe,EAAE,IAAI;IACrB,SAAS,EAAE,KAAK;IAChB,cAAc,EAAE,KAAK;IACrB,oBAAoB,EAAE,KAAK;CAC5B,CAAC;AAEF,SAAS,gBAAgB,CAAmB,QAA4B;IACtE,OAAQ,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAS,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,kGAAkG;AAClG,MAAM,CAAC,MAAM,iCAAiC,GAAqC,gBAAgB,CACjG,kCAAkC,CACnC,CAAC;AAEF,yFAAyF;AACzF,MAAM,CAAC,MAAM,6BAA6B,GAAkC,gBAAgB,CAAC,8BAA8B,CAAC,CAAC;AAE7H,qGAAqG;AACrG,MAAM,CAAC,MAAM,mCAAmC,GAAsC,gBAAgB,CACpG,oCAAoC,CACrC,CAAC;AAEF,iGAAiG;AACjG,6CAA6C;AAC7C,MAAM,wBAAwB,GAAG;IAC/B,IAAI,EAAE,kCAAkC;IACxC,IAAI,EAAE,8BAA8B;CACqB,CAAC;AAO5D,qFAAqF;AACrF,MAAM,UAAU,wBAAwB,CAAC,GAAwB;IAC/D,MAAM,QAAQ,GAA4B,wBAAwB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACjF,OAAO,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;AACvC,CAAC","sourcesContent":["// Which safety-case and take-it-down statuses are still open work. The Safety Case Console's\n// active lists, the ops snapshot's Legal-Clocks counts, and the closed-case lookup's reopen check\n// all read these, so the console an operator clicks through to and the count that sent them\n// there always agree. A case stays active until its worker verifies a terminal status: a close in\n// progress (`processing`) and a worker out of retries (`failed`) are still open work.\n//\n// Each status is classified in a map over its whole union, so a new status does not build until\n// it is placed. Type-only imports keep this module free of runtime dependencies for the backend\n// bundles that load it.\n\nimport type { ChildSafetyWorkStatus, SafetyCaseLane } from '../doc-schemas/safety/case.js';\nimport type { NciiInternalStatus, TakeItDownPublicStatus } from '../doc-schemas/safety/foundation.js';\n\nconst CHILD_SAFETY_WORK_STATUS_IS_ACTIVE: Record<ChildSafetyWorkStatus, boolean> = {\n new: true,\n triaged: true,\n reporting: true,\n actioning: true,\n processing: true,\n failed: true,\n operationallyResolved: false,\n};\n\nconst NCII_INTERNAL_STATUS_IS_ACTIVE: Record<NciiInternalStatus, boolean> = {\n open: true,\n removalInProgress: true,\n processing: true,\n failed: true,\n removed: false,\n rejected: false,\n closed: false,\n};\n\nconst TAKE_IT_DOWN_PUBLIC_STATUS_IS_ACTIVE: Record<TakeItDownPublicStatus, boolean> = {\n received: true,\n needsMoreInfo: true,\n validInProgress: true,\n completed: false,\n unableToLocate: false,\n invalidGeneralReason: false,\n};\n\nfunction activeStatusesOf<S extends string>(isActive: Record<S, boolean>): readonly S[] {\n return (Object.keys(isActive) as S[]).filter((status) => isActive[status]);\n}\n\n/** Child-safety case work statuses still open (the `workStatus` an active-case query matches). */\nexport const CHILD_SAFETY_ACTIVE_WORK_STATUSES: readonly ChildSafetyWorkStatus[] = activeStatusesOf(\n CHILD_SAFETY_WORK_STATUS_IS_ACTIVE,\n);\n\n/** NCII case statuses still open (the `internalStatus` an active-case query matches). */\nexport const NCII_ACTIVE_INTERNAL_STATUSES: readonly NciiInternalStatus[] = activeStatusesOf(NCII_INTERNAL_STATUS_IS_ACTIVE);\n\n/** Take-it-down request statuses still open (the `publicStatus` an active-request query matches). */\nexport const TAKE_IT_DOWN_ACTIVE_PUBLIC_STATUSES: readonly TakeItDownPublicStatus[] = activeStatusesOf(\n TAKE_IT_DOWN_PUBLIC_STATUS_IS_ACTIVE,\n);\n\n// Keyed by the canonical lane union: a lane added to or renamed in SafetyCaseLaneSchema does not\n// build until its status set is placed here.\nconst STATUS_IS_ACTIVE_BY_LANE = {\n csam: CHILD_SAFETY_WORK_STATUS_IS_ACTIVE,\n ncii: NCII_INTERNAL_STATUS_IS_ACTIVE,\n} satisfies Record<SafetyCaseLane, Record<string, boolean>>;\n\n/** A safety case's lane and its status in that lane's own status set. */\nexport type SafetyCaseStatusRef = {\n [Lane in SafetyCaseLane]: { caseType: Lane; status: keyof (typeof STATUS_IS_ACTIVE_BY_LANE)[Lane] };\n}[SafetyCaseLane];\n\n/** Whether a safety case is still open work, read from its own lane's status set. */\nexport function isActiveSafetyCaseStatus(ref: SafetyCaseStatusRef): boolean {\n const isActive: Record<string, boolean> = STATUS_IS_ACTIVE_BY_LANE[ref.caseType];\n return isActive[ref.status] === true;\n}\n"]}
|
|
@@ -52,6 +52,6 @@ export declare const HALL_MEDIA_REAPER_CLAIM_LEASE_MS: number;
|
|
|
52
52
|
* rolling-cursor state (`SweepStateSchema`), so each pass owns exactly one doc and its cursor is
|
|
53
53
|
* never shared with another pass.
|
|
54
54
|
*/
|
|
55
|
-
export declare const SWEEP_STATE_NAMES: readonly ["orphanRegistrationCleanup", "reconcileAccountStatus", "reconcilePublicUsers", "hallMediaReaperAssetPhase", "quarantineEnqueueBackstop", "ncmecEnqueueBackstop", "staleSafetyCaseAlertSweep", "csamStrandedProcessing", "nciiStrandedProcessing", "expireRejectedMedia", "cleanupOrphanUploads", "mediaReconcileUnpublishedAssets", "mediaReconcileUnreferencedBroadAssets", "nciiEvidenceOrphanSweeper", "nciiRetentionClosedRequests"];
|
|
55
|
+
export declare const SWEEP_STATE_NAMES: readonly ["orphanRegistrationCleanup", "reconcileAccountStatus", "reconcilePublicUsers", "hallMediaReaperAssetPhase", "quarantineEnqueueBackstop", "ncmecEnqueueBackstop", "staleSafetyCaseAlertSweep", "csamStrandedProcessing", "nciiStrandedProcessing", "expireRejectedMedia", "cleanupOrphanUploads", "mediaReconcileUnpublishedAssets", "mediaReconcileUnreferencedBroadAssets", "nciiEvidenceOrphanSweeper", "nciiRetentionClosedRequests", "reconcilePledgeRefundApprovals", "crossoverServingDenyReconcile", "crossoverPhotoDnaReconcile"];
|
|
56
56
|
export type SweepStateName = (typeof SWEEP_STATE_NAMES)[number];
|
|
57
57
|
//# sourceMappingURL=scheduled-jobs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduled-jobs.d.ts","sourceRoot":"","sources":["../../src/constants/scheduled-jobs.ts"],"names":[],"mappings":"AAIA,oEAAoE;AACpE,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C,wEAAwE;AACxE,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD,uEAAuE;AACvE,eAAO,MAAM,iCAAiC,KAAK,CAAC;AAIpD;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B,QAA2B,CAAC;AAEnE;6BAC6B;AAC7B,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C;;;;;;;GAOG;AACH,eAAO,MAAM,iCAAiC,QAAsB,CAAC;AACrE,eAAO,MAAM,gCAAgC,QAA2B,CAAC;AAEzE;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAE3C;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC,QAAiB,CAAC;AAI/D;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"scheduled-jobs.d.ts","sourceRoot":"","sources":["../../src/constants/scheduled-jobs.ts"],"names":[],"mappings":"AAIA,oEAAoE;AACpE,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C,wEAAwE;AACxE,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD,uEAAuE;AACvE,eAAO,MAAM,iCAAiC,KAAK,CAAC;AAIpD;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B,QAA2B,CAAC;AAEnE;6BAC6B;AAC7B,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C;;;;;;;GAOG;AACH,eAAO,MAAM,iCAAiC,QAAsB,CAAC;AACrE,eAAO,MAAM,gCAAgC,QAA2B,CAAC;AAEzE;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAE3C;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC,QAAiB,CAAC;AAI/D;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,qhBAmBpB,CAAC;AACX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -72,5 +72,8 @@ export const SWEEP_STATE_NAMES = [
|
|
|
72
72
|
'mediaReconcileUnreferencedBroadAssets',
|
|
73
73
|
'nciiEvidenceOrphanSweeper',
|
|
74
74
|
'nciiRetentionClosedRequests',
|
|
75
|
+
'reconcilePledgeRefundApprovals',
|
|
76
|
+
'crossoverServingDenyReconcile',
|
|
77
|
+
'crossoverPhotoDnaReconcile',
|
|
75
78
|
];
|
|
76
79
|
//# sourceMappingURL=scheduled-jobs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduled-jobs.js","sourceRoot":"","sources":["../../src/constants/scheduled-jobs.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAEzD,6BAA6B;AAE7B,oEAAoE;AACpE,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAE9C,wEAAwE;AACxE,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AAEjD,uEAAuE;AACvE,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,CAAC;AAEpD,mCAAmC;AAEnC;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEnE;6BAC6B;AAC7B,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACrE,MAAM,CAAC,MAAM,gCAAgC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEzE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE/D,sBAAsB;AAEtB;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,2BAA2B;IAC3B,wBAAwB;IACxB,sBAAsB;IACtB,2BAA2B;IAC3B,2BAA2B;IAC3B,sBAAsB;IACtB,2BAA2B;IAC3B,wBAAwB;IACxB,wBAAwB;IACxB,qBAAqB;IACrB,sBAAsB;IACtB,iCAAiC;IACjC,uCAAuC;IACvC,2BAA2B;IAC3B,6BAA6B;
|
|
1
|
+
{"version":3,"file":"scheduled-jobs.js","sourceRoot":"","sources":["../../src/constants/scheduled-jobs.ts"],"names":[],"mappings":"AAAA,yDAAyD;AAEzD,6BAA6B;AAE7B,oEAAoE;AACpE,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAE9C,wEAAwE;AACxE,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AAEjD,uEAAuE;AACvE,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,CAAC;AAEpD,mCAAmC;AAEnC;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEnE;6BAC6B;AAC7B,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AACrE,MAAM,CAAC,MAAM,gCAAgC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEzE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE/D,sBAAsB;AAEtB;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,2BAA2B;IAC3B,wBAAwB;IACxB,sBAAsB;IACtB,2BAA2B;IAC3B,2BAA2B;IAC3B,sBAAsB;IACtB,2BAA2B;IAC3B,wBAAwB;IACxB,wBAAwB;IACxB,qBAAqB;IACrB,sBAAsB;IACtB,iCAAiC;IACjC,uCAAuC;IACvC,2BAA2B;IAC3B,6BAA6B;IAC7B,gCAAgC;IAChC,+BAA+B;IAC/B,4BAA4B;CACpB,CAAC","sourcesContent":["// Scheduled-job intervals, batch sizes, and source URLs.\n\n// --- Admin task cleanup ---\n\n/** Interval in minutes for the admin-task cleanup scheduled job. */\nexport const ADMIN_TASK_CLEANUP_INTERVAL = 15;\n\n/** Batch size of expired task checkouts processed per scheduled run. */\nexport const ADMIN_TASK_EXPIRED_BATCH_SIZE = 500;\n\n/** Safety cap on iterations within a single admin-task cleanup run. */\nexport const ADMIN_TASK_CLEANUP_MAX_ITERATIONS = 10;\n\n// --- Hall-media orphan reaper ---\n\n/**\n * How long Hall-media copies are left alone before the orphan reaper may reclaim them — both a\n * Hall-owned asset (asset phase, measured from its `createdAt`) and the objects a write intent\n * names (copy-intent phase: recording a copy's or a first ingest's intent sets its `reapAfter`\n * this far out, far beyond any ingest's processing and retry time). It must exceed\n * the longest retry window of the publish trigger `onThresholdItemReviewed` (about a day), since\n * a pending retry re-derives the same deterministic copy and attaches its bytes. It also leaves a\n * publish that parked partway time to be unwound, resubmitted, and re-driven onto the same\n * destination while its earlier objects are still there to reuse.\n */\nexport const HALL_MEDIA_ORPHAN_GRACE_MS = 14 * 24 * 60 * 60 * 1000;\n\n/** Most candidates each reaper phase takes up per pass: assets in the asset phase, due intents in\n * the copy-intent phase. */\nexport const HALL_MEDIA_REAPER_PAGE_SIZE = 100;\n\n/**\n * Deferral backoff for both reaper phases — a copy intent the sweep cannot finish yet\n * (`reapAttemptCount`) and an asset-phase candidate it cannot positively clear (a cursor\n * `deferred` entry's `attemptCount`). With `n` the count after the deferral that is being\n * scheduled, the item is next due `min(BASE × 2^(n−1), MAX)` from now: 1, 2, 4, 8, then 14 days\n * from there on. The base is the reaper's daily cadence, since any shorter delay is simply the\n * next pass; the cap bounds how long a released hold or a recovered read waits to be noticed.\n */\nexport const HALL_MEDIA_REAPER_BACKOFF_BASE_MS = 24 * 60 * 60 * 1000;\nexport const HALL_MEDIA_REAPER_BACKOFF_MAX_MS = 14 * 24 * 60 * 60 * 1000;\n\n/**\n * Most rows one pass holds in its sweep-state `deferred` set — the rows its rolling cursor moved past\n * without positively clearing. Every pass retries the entries that are due, each retry re-reading the\n * row, so for the Hall-media orphan reaper the bound keeps that work to half of a\n * HALL_MEDIA_REAPER_PAGE_SIZE page on top of the pass's own page, and it keeps the sweep-state doc a\n * few kilobytes. A row a pass cannot positively clear is rare, so a full set means something\n * systemic is failing — the signal to stop and report, not to keep growing the list.\n */\nexport const SWEEP_STATE_MAX_DEFERRED = 50;\n\n/**\n * How long the copy-intent sweep holds a claim on an intent. Claiming moves the intent to\n * `reaping` and stamps `reapClaimedAt`, and that stamp is the claim's fencing token. Once the claim\n * is this old it has expired: a later sweep may take the intent over and re-stamp it, and the copy\n * path may take the `reaping` intent back to `copying`. It must far exceed the timeout of the\n * reaper function `reapOrphanedHallMediaCopies` (300 s), so a live pass never loses its claim, and\n * stay far below the retry budget of the publish trigger `onThresholdItemReviewed` (about a day),\n * so a publish stranded behind an abandoned claim always recovers inside it.\n */\nexport const HALL_MEDIA_REAPER_CLAIM_LEASE_MS = 60 * 60 * 1000;\n\n// --- Sweep state ---\n\n/**\n * The `sweepState/{sweepName}` doc ids: one per scheduled pass that keeps durable cadence or\n * rolling-cursor state (`SweepStateSchema`), so each pass owns exactly one doc and its cursor is\n * never shared with another pass.\n */\nexport const SWEEP_STATE_NAMES = [\n 'orphanRegistrationCleanup',\n 'reconcileAccountStatus',\n 'reconcilePublicUsers',\n 'hallMediaReaperAssetPhase',\n 'quarantineEnqueueBackstop',\n 'ncmecEnqueueBackstop',\n 'staleSafetyCaseAlertSweep',\n 'csamStrandedProcessing',\n 'nciiStrandedProcessing',\n 'expireRejectedMedia',\n 'cleanupOrphanUploads',\n 'mediaReconcileUnpublishedAssets',\n 'mediaReconcileUnreferencedBroadAssets',\n 'nciiEvidenceOrphanSweeper',\n 'nciiRetentionClosedRequests',\n 'reconcilePledgeRefundApprovals',\n 'crossoverServingDenyReconcile',\n 'crossoverPhotoDnaReconcile',\n] as const;\nexport type SweepStateName = (typeof SWEEP_STATE_NAMES)[number];\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const TTT_TELEMETRY_CONTENT_POLICY: {
|
|
2
|
+
/** Keys whose text value is diagnostic: the descriptors capture sites set. */
|
|
3
|
+
readonly diagnosticKeys: readonly ["uid", "operation", "function", "step", "stage", "phase", "kind", "type", "category", "action", "leg", "reason", "code", "claim", "remaining", "scores", "issues", "groupKey", "context", "diagnostic", "reportReason", "deadline_lane", "monitor_stage", "safe_code", "leftover_cause", "ncii_inventory_fallback", "validation_error", "extra"];
|
|
4
|
+
/** An identifier, hash, code, or enum value named by its suffix (`caseId`, `targetKeyHash`, `fileOrigin`). */
|
|
5
|
+
readonly diagnosticKeySuffixes: readonly ["Id", "Ids", "Uid", "Uids", "Hash", "Type", "Kind", "Status", "Code", "Outcome", "Origin", "Source"];
|
|
6
|
+
/** The context capture sites name the running function in (`scope.setContext('function', { name })`). */
|
|
7
|
+
readonly codeNameContexts: readonly ["function"];
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=telemetry-content-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-content-policy.d.ts","sourceRoot":"","sources":["../../src/constants/telemetry-content-policy.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,4BAA4B;IACvC,8EAA8E;;IAkC9E,8GAA8G;;IAE9G,yGAAyG;;CAEjG,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// TTT's telemetry content policy (QUALITY-106): which keys of a monitoring event may carry text.
|
|
2
|
+
// monitoring-core's `createTelemetryContentPolicy` applies it, so the Functions backend and the
|
|
3
|
+
// Next server and edge runtimes cut every event to the same allowlist. Plain data with no
|
|
4
|
+
// monitoring-core import, so ttt-core takes no dependency on it; the shape matches that factory's
|
|
5
|
+
// options.
|
|
6
|
+
//
|
|
7
|
+
// Widening either list to a key that can hold prose, a stored document, a file name, or a storage
|
|
8
|
+
// or document path breaks QUALITY-106: only identifiers, codes, and enum values may ride as text.
|
|
9
|
+
export const TTT_TELEMETRY_CONTENT_POLICY = {
|
|
10
|
+
/** Keys whose text value is diagnostic: the descriptors capture sites set. */
|
|
11
|
+
diagnosticKeys: [
|
|
12
|
+
'uid',
|
|
13
|
+
'operation',
|
|
14
|
+
'function',
|
|
15
|
+
'step',
|
|
16
|
+
'stage',
|
|
17
|
+
'phase',
|
|
18
|
+
'kind',
|
|
19
|
+
'type',
|
|
20
|
+
'category',
|
|
21
|
+
'action',
|
|
22
|
+
'leg',
|
|
23
|
+
'reason',
|
|
24
|
+
'code',
|
|
25
|
+
'claim',
|
|
26
|
+
'remaining',
|
|
27
|
+
'scores',
|
|
28
|
+
'issues',
|
|
29
|
+
'groupKey',
|
|
30
|
+
'context',
|
|
31
|
+
'diagnostic',
|
|
32
|
+
'reportReason',
|
|
33
|
+
// The snake_case tag keys the safety alarms, the NCII inventory fallback, and post validation set.
|
|
34
|
+
'deadline_lane',
|
|
35
|
+
'monitor_stage',
|
|
36
|
+
'safe_code',
|
|
37
|
+
'leftover_cause',
|
|
38
|
+
'ncii_inventory_fallback',
|
|
39
|
+
'validation_error',
|
|
40
|
+
// `captureException(error, { extra: {…} })` lands as an extra named `extra` (monitoring-core's
|
|
41
|
+
// capture context): the container passes and its own keys are checked.
|
|
42
|
+
'extra',
|
|
43
|
+
],
|
|
44
|
+
/** An identifier, hash, code, or enum value named by its suffix (`caseId`, `targetKeyHash`, `fileOrigin`). */
|
|
45
|
+
diagnosticKeySuffixes: ['Id', 'Ids', 'Uid', 'Uids', 'Hash', 'Type', 'Kind', 'Status', 'Code', 'Outcome', 'Origin', 'Source'],
|
|
46
|
+
/** The context capture sites name the running function in (`scope.setContext('function', { name })`). */
|
|
47
|
+
codeNameContexts: ['function'],
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=telemetry-content-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-content-policy.js","sourceRoot":"","sources":["../../src/constants/telemetry-content-policy.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,gGAAgG;AAChG,0FAA0F;AAC1F,kGAAkG;AAClG,WAAW;AACX,EAAE;AACF,kGAAkG;AAClG,kGAAkG;AAElG,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,8EAA8E;IAC9E,cAAc,EAAE;QACd,KAAK;QACL,WAAW;QACX,UAAU;QACV,MAAM;QACN,OAAO;QACP,OAAO;QACP,MAAM;QACN,MAAM;QACN,UAAU;QACV,QAAQ;QACR,KAAK;QACL,QAAQ;QACR,MAAM;QACN,OAAO;QACP,WAAW;QACX,QAAQ;QACR,QAAQ;QACR,UAAU;QACV,SAAS;QACT,YAAY;QACZ,cAAc;QACd,mGAAmG;QACnG,eAAe;QACf,eAAe;QACf,WAAW;QACX,gBAAgB;QAChB,yBAAyB;QACzB,kBAAkB;QAClB,+FAA+F;QAC/F,uEAAuE;QACvE,OAAO;KACR;IACD,8GAA8G;IAC9G,qBAAqB,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC;IAC5H,yGAAyG;IACzG,gBAAgB,EAAE,CAAC,UAAU,CAAC;CACtB,CAAC","sourcesContent":["// TTT's telemetry content policy (QUALITY-106): which keys of a monitoring event may carry text.\n// monitoring-core's `createTelemetryContentPolicy` applies it, so the Functions backend and the\n// Next server and edge runtimes cut every event to the same allowlist. Plain data with no\n// monitoring-core import, so ttt-core takes no dependency on it; the shape matches that factory's\n// options.\n//\n// Widening either list to a key that can hold prose, a stored document, a file name, or a storage\n// or document path breaks QUALITY-106: only identifiers, codes, and enum values may ride as text.\n\nexport const TTT_TELEMETRY_CONTENT_POLICY = {\n /** Keys whose text value is diagnostic: the descriptors capture sites set. */\n diagnosticKeys: [\n 'uid',\n 'operation',\n 'function',\n 'step',\n 'stage',\n 'phase',\n 'kind',\n 'type',\n 'category',\n 'action',\n 'leg',\n 'reason',\n 'code',\n 'claim',\n 'remaining',\n 'scores',\n 'issues',\n 'groupKey',\n 'context',\n 'diagnostic',\n 'reportReason',\n // The snake_case tag keys the safety alarms, the NCII inventory fallback, and post validation set.\n 'deadline_lane',\n 'monitor_stage',\n 'safe_code',\n 'leftover_cause',\n 'ncii_inventory_fallback',\n 'validation_error',\n // `captureException(error, { extra: {…} })` lands as an extra named `extra` (monitoring-core's\n // capture context): the container passes and its own keys are checked.\n 'extra',\n ],\n /** An identifier, hash, code, or enum value named by its suffix (`caseId`, `targetKeyHash`, `fileOrigin`). */\n diagnosticKeySuffixes: ['Id', 'Ids', 'Uid', 'Uids', 'Hash', 'Type', 'Kind', 'Status', 'Code', 'Outcome', 'Origin', 'Source'],\n /** The context capture sites name the running function in (`scope.setContext('function', { name })`). */\n codeNameContexts: ['function'],\n} as const;\n"]}
|
|
@@ -30,6 +30,9 @@ export declare const SweepStateNameSchema: z.ZodEnum<{
|
|
|
30
30
|
mediaReconcileUnreferencedBroadAssets: "mediaReconcileUnreferencedBroadAssets";
|
|
31
31
|
nciiEvidenceOrphanSweeper: "nciiEvidenceOrphanSweeper";
|
|
32
32
|
nciiRetentionClosedRequests: "nciiRetentionClosedRequests";
|
|
33
|
+
reconcilePledgeRefundApprovals: "reconcilePledgeRefundApprovals";
|
|
34
|
+
crossoverServingDenyReconcile: "crossoverServingDenyReconcile";
|
|
35
|
+
crossoverPhotoDnaReconcile: "crossoverPhotoDnaReconcile";
|
|
33
36
|
}>;
|
|
34
37
|
export declare const SweepDeferredRowSchema: z.ZodObject<{
|
|
35
38
|
key: z.ZodString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend-state.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/backend-state.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAexB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;iBAa/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,oEAAoE;AACpE,eAAO,MAAM,oBAAoB
|
|
1
|
+
{"version":3,"file":"backend-state.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/backend-state.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAexB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;iBAa/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,oEAAoE;AACpE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;EAA4B,CAAC;AAO9D,eAAO,MAAM,sBAAsB;;;;;kBAUxB,CAAC;AACZ,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAUtE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;iBAgBzB,CAAC;AACL,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAU1D,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;;iBAc7C,CAAC;AACH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAS9F,eAAO,MAAM,kCAAkC;;;;;;;;;;;;iBAgB7C,CAAC;AACH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAQ9F,eAAO,MAAM,mCAAmC;;;;;;;;iBAU9C,CAAC;AACH,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC"}
|
|
@@ -38,6 +38,30 @@ export declare function isPledgeDisputeEventApplicable(recorded: {
|
|
|
38
38
|
disputeId: string;
|
|
39
39
|
state: PledgeDisputeState;
|
|
40
40
|
}): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* The pledge's dispute number for a dispute event: the recorded number while the event is about the
|
|
43
|
+
* recorded dispute (the provider ref's `disputeId`), one more for any other dispute — so the first
|
|
44
|
+
* dispute is 1 and each later one adds one. The number is what the member-readable pledge carries in
|
|
45
|
+
* place of Stripe's dispute id, which stays on the server-only provider ref.
|
|
46
|
+
*/
|
|
47
|
+
export declare function pledgeDisputeNumberForEvent(recorded: {
|
|
48
|
+
disputeId: string | null;
|
|
49
|
+
disputeNumber: number;
|
|
50
|
+
}, eventDisputeId: string): number;
|
|
51
|
+
/**
|
|
52
|
+
* Whether a pledge's dispute fields may move from `before` to `after` — the rule an integrity check
|
|
53
|
+
* reads from the pledge alone. Under the same dispute number the state only climbs the ladder (or stays,
|
|
54
|
+
* as a redelivery or a refund leaves it); a number one higher is a new dispute, which starts its own
|
|
55
|
+
* ladder at any state but `none` (its close may arrive before its opening). Any other number change is
|
|
56
|
+
* not a legal transition.
|
|
57
|
+
*/
|
|
58
|
+
export declare function isPledgeDisputeTransitionLegal(before: {
|
|
59
|
+
disputeNumber: number;
|
|
60
|
+
disputeState: PledgeDisputeState;
|
|
61
|
+
}, after: {
|
|
62
|
+
disputeNumber: number;
|
|
63
|
+
disputeState: PledgeDisputeState;
|
|
64
|
+
}): boolean;
|
|
41
65
|
export declare const PledgePaymentSchema: z.ZodObject<{
|
|
42
66
|
pledgePaymentId: z.ZodString;
|
|
43
67
|
userId: z.ZodString;
|
|
@@ -59,6 +83,7 @@ export declare const PledgePaymentSchema: z.ZodObject<{
|
|
|
59
83
|
won: "won";
|
|
60
84
|
lost: "lost";
|
|
61
85
|
}>;
|
|
86
|
+
disputeNumber: z.ZodNumber;
|
|
62
87
|
createdAt: z.ZodNumber;
|
|
63
88
|
updatedAt: z.ZodNumber;
|
|
64
89
|
}, z.core.$strip>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payments.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/payments.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,uGAAuG;AACvG,eAAO,MAAM,oBAAoB,sCAAuC,CAAC;AACzE,eAAO,MAAM,uBAAuB;;;;EAA+B,CAAC;AACpE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,qGAAqG;AACrG,eAAO,MAAM,qBAAqB,iDAAkD,CAAC;AACrF,eAAO,MAAM,wBAAwB;;;;;EAAgC,CAAC;AACtE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAS1E,qFAAqF;AACrF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAExE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,kBAAkB,EAAE,EAAE,EAAE,kBAAkB,GAAG,OAAO,CAEhG;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,EACjE,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,GACtD,OAAO,CAGT;AAMD,eAAO,MAAM,mBAAmB
|
|
1
|
+
{"version":3,"file":"payments.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/payments.ts"],"names":[],"mappings":"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"}
|
|
@@ -43,6 +43,30 @@ export function isPledgeDisputeEventApplicable(recorded, event) {
|
|
|
43
43
|
return true;
|
|
44
44
|
return isPledgeDisputeAdvance(recorded.state, event.state);
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* The pledge's dispute number for a dispute event: the recorded number while the event is about the
|
|
48
|
+
* recorded dispute (the provider ref's `disputeId`), one more for any other dispute — so the first
|
|
49
|
+
* dispute is 1 and each later one adds one. The number is what the member-readable pledge carries in
|
|
50
|
+
* place of Stripe's dispute id, which stays on the server-only provider ref.
|
|
51
|
+
*/
|
|
52
|
+
export function pledgeDisputeNumberForEvent(recorded, eventDisputeId) {
|
|
53
|
+
return recorded.disputeId === eventDisputeId ? recorded.disputeNumber : recorded.disputeNumber + 1;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Whether a pledge's dispute fields may move from `before` to `after` — the rule an integrity check
|
|
57
|
+
* reads from the pledge alone. Under the same dispute number the state only climbs the ladder (or stays,
|
|
58
|
+
* as a redelivery or a refund leaves it); a number one higher is a new dispute, which starts its own
|
|
59
|
+
* ladder at any state but `none` (its close may arrive before its opening). Any other number change is
|
|
60
|
+
* not a legal transition.
|
|
61
|
+
*/
|
|
62
|
+
export function isPledgeDisputeTransitionLegal(before, after) {
|
|
63
|
+
if (after.disputeNumber === before.disputeNumber) {
|
|
64
|
+
return after.disputeState === before.disputeState || isPledgeDisputeAdvance(before.disputeState, after.disputeState);
|
|
65
|
+
}
|
|
66
|
+
if (after.disputeNumber === before.disputeNumber + 1)
|
|
67
|
+
return after.disputeState !== 'none';
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
46
70
|
// pledgePayments/{pledgePaymentId} — public-safe canonical money record. One doc per completed
|
|
47
71
|
// pledge; never deleted/archived. No Stripe IDs, no supporter message. Auth-readable; server-only
|
|
48
72
|
// writes, by the Stripe webhook alone. netAmount = max(0, amount - refundedAmount - disputeLostAmount)
|
|
@@ -59,10 +83,18 @@ export const PledgePaymentSchema = z.object({
|
|
|
59
83
|
status: z.literal('completed'),
|
|
60
84
|
refundState: PledgeRefundStateSchema,
|
|
61
85
|
disputeState: PledgeDisputeStateSchema,
|
|
86
|
+
// How many disputes the pledge has had: 0 until the first, then 1, 2, … (pledgeDisputeNumberForEvent).
|
|
87
|
+
// It tells one dispute from the next on this member-readable doc; Stripe's dispute id stays on the
|
|
88
|
+
// server-only provider ref.
|
|
89
|
+
disputeNumber: z.number().int().nonnegative(),
|
|
62
90
|
// NO ageAttestedAt here: age-attestation evidence is server-only and lives on
|
|
63
91
|
// PledgePaymentProviderRefSchema. This doc is auth-readable by every signed-in member.
|
|
64
92
|
createdAt: z.number(),
|
|
65
93
|
updatedAt: z.number(),
|
|
94
|
+
}).superRefine((val, ctx) => {
|
|
95
|
+
if ((val.disputeNumber === 0) !== (val.disputeState === 'none')) {
|
|
96
|
+
ctx.addIssue({ code: 'custom', path: ['disputeNumber'] });
|
|
97
|
+
}
|
|
66
98
|
});
|
|
67
99
|
// pledgePaymentProviderRefs/{pledgePaymentId} — server-only Stripe references for reconciliation
|
|
68
100
|
// and refund/dispute lookup, PLUS the age-attestation consent evidence. Rule is permanently
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payments.js","sourceRoot":"","sources":["../../src/doc-schemas/payments.ts"],"names":[],"mappings":"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","sourcesContent":["// Payment / pledge Firestore document SCHEMAS — the public-safe pledge ledger and its\n// server-only companions: provider refs (Stripe IDs), the idempotency sentinel, the\n// independent integrity trail, and the paid-event quarantine queue. Types inferred via\n// z.infer. Money data lives here, never in social.ts.\n// See ttt-prod docs/design/donation-payment-system.md (the design owner for the\n// pledge/Stripe flow).\n\nimport { z } from 'zod';\nimport { LegalReviewNoticeReceiptSchema } from './legal-review-notice.js';\nimport { MAX_INTERNAL_REASON_LENGTH } from '../constants/business-admin.js';\n\n/** How much of a pledge has been refunded: `partial` while some net remains, `full` once none does. */\nexport const PLEDGE_REFUND_STATES = ['none', 'partial', 'full'] as const;\nexport const PledgeRefundStateSchema = z.enum(PLEDGE_REFUND_STATES);\nexport type PledgeRefundState = z.infer<typeof PledgeRefundStateSchema>;\n\n/** Where a chargeback dispute stands: `underReview` while open, then `won` or `lost` once closed. */\nexport const PLEDGE_DISPUTE_STATES = ['none', 'underReview', 'won', 'lost'] as const;\nexport const PledgeDisputeStateSchema = z.enum(PLEDGE_DISPUTE_STATES);\nexport type PledgeDisputeState = z.infer<typeof PledgeDisputeStateSchema>;\n\nconst PLEDGE_DISPUTE_STATE_RANK: Record<PledgeDisputeState, number> = {\n none: 0,\n underReview: 1,\n won: 2,\n lost: 2,\n};\n\n/** A dispute state's place on the one-way ladder none < underReview < won | lost. */\nexport function pledgeDisputeStateRank(state: PledgeDisputeState): number {\n return PLEDGE_DISPUTE_STATE_RANK[state];\n}\n\n/**\n * Whether moving ONE dispute from `from` to `to` goes up the ladder. Stripe can deliver a\n * dispute's events late or twice, so within one dispute a closed dispute never reopens to\n * `underReview`, and `won` and `lost` never replace each other.\n */\nexport function isPledgeDisputeAdvance(from: PledgeDisputeState, to: PledgeDisputeState): boolean {\n return pledgeDisputeStateRank(to) > pledgeDisputeStateRank(from);\n}\n\n/**\n * Whether a dispute event may set the pledge's dispute state. The ladder holds per dispute: an\n * event for a different dispute than the recorded `disputeId` (the first one, or a later dispute\n * on the same charge) starts its own ladder, and an event for the recorded dispute applies only as\n * an advance. Ordering across disputes is the observation stamp's job — the handler first refuses\n * an event no newer than `disputeObservedAt`, so a late event of an earlier dispute never lands.\n */\nexport function isPledgeDisputeEventApplicable(\n recorded: { disputeId: string | null; state: PledgeDisputeState },\n event: { disputeId: string; state: PledgeDisputeState },\n): boolean {\n if (recorded.disputeId !== event.disputeId) return true;\n return isPledgeDisputeAdvance(recorded.state, event.state);\n}\n\n// pledgePayments/{pledgePaymentId} — public-safe canonical money record. One doc per completed\n// pledge; never deleted/archived. No Stripe IDs, no supporter message. Auth-readable; server-only\n// writes, by the Stripe webhook alone. netAmount = max(0, amount - refundedAmount - disputeLostAmount)\n// is the sum() target; the refund and dispute handlers recompute it from Stripe's totals.\nexport const PledgePaymentSchema = z.object({\n pledgePaymentId: z.string(),\n userId: z.string(),\n amount: z.number(), // gross cents charged (Stripe-confirmed amount_total)\n refundedAmount: z.number(), // cumulative refunded cents, from the Charge's amount_refunded; 0 on a new pledge\n disputeLostAmount: z.number(), // cents withdrawn on a lost dispute; 0 otherwise\n netAmount: z.number(), // max(0, amount - refundedAmount - disputeLostAmount); sum() target\n currency: z.string(), // \"usd\"\n paymentInstrument: z.literal('card'),\n status: z.literal('completed'),\n refundState: PledgeRefundStateSchema,\n disputeState: PledgeDisputeStateSchema,\n // NO ageAttestedAt here: age-attestation evidence is server-only and lives on\n // PledgePaymentProviderRefSchema. This doc is auth-readable by every signed-in member.\n createdAt: z.number(),\n updatedAt: z.number(),\n});\nexport type PledgePayment = z.infer<typeof PledgePaymentSchema>;\n\n// pledgePaymentProviderRefs/{pledgePaymentId} — server-only Stripe references for reconciliation\n// and refund/dispute lookup, PLUS the age-attestation consent evidence. Rule is permanently\n// `if false` (Admin SDK only) so no Stripe IDs ever sit on an auth-readable doc. One doc per pledge\n// (singular).\nexport const PledgePaymentProviderRefSchema = z.object({\n pledgePaymentId: z.string(),\n userId: z.string(),\n stripeSessionId: z.string(),\n paymentIntentId: z.string(),\n latestChargeId: z.string().nullable(), // resolved when known; null at launch if not fetched\n refundIds: z.array(z.string()), // every Stripe refund id seen on the charge; [] on a new pledge\n disputeId: z.string().nullable(), // the dispute the ledger's disputeState describes (the latest opened), null until one opens\n // Server timestamp (ms) of the checkout's 18+/public-disclosure attestation, stamped at session\n // creation and carried through Stripe metadata. A paid session missing it is quarantined. It is\n // fraud-evidence plumbing, not transparency data, so it rides THIS server-only doc and never the\n // member-readable pledgePayments ledger (docs/design/donation-payment-system.md § Data model).\n ageAttestedAt: z.number(),\n // The founder legal-review notice acknowledgment given at checkout (its own required checkbox\n // on every pledge while the notice is active): the revision and server time, stamped at session\n // creation and carried through the Stripe metadata like `ageAttestedAt`. Absent when the notice\n // was off. Evidence, not transparency data — it rides this server-only doc only.\n legalReviewNotice: LegalReviewNoticeReceiptSchema.optional(),\n // The refund an approval asks Stripe for: written in the transaction that moves its request to\n // `approving` (before Stripe is called), `refundId` stamped once Stripe answers, removed when the\n // request reaches `completed` or `failed`. A request is finished only by a refund matching it.\n refundCorrelation: z\n .object({\n requestId: z.string().min(1),\n intendedAmount: z.number().int().positive(),\n refundId: z.string().min(1).optional(),\n })\n .optional(),\n // The Stripe event time (epoch ms) the refund handler and the dispute handler last applied. Stripe\n // can deliver events out of order, so each handler applies an event only when it is newer.\n refundObservedAt: z.number().optional(),\n disputeObservedAt: z.number().optional(),\n // Stripe's reason for the last failed refund, kept server-side for the admin following up.\n lastRefundFailureReason: z.string().max(MAX_INTERNAL_REASON_LENGTH).optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n});\nexport type PledgePaymentProviderRef = z.infer<typeof PledgePaymentProviderRefSchema>;\n\n// pledgePaymentTotals/summary — the stored running-totals singleton behind every \"total raised\"\n// surface. Incremented via FieldValue.increment INSIDE the Stripe webhook's pledge-record\n// transaction (same commit as the pledgePayments doc — the two can never drift on a completed\n// pledge); the refund and dispute handlers adjust it in the transaction that changes the pledge,\n// through pledgePaymentTotalsOf (utils/pledge-totals). Auth-readable, server-only\n// writes. An idempotent recompute script rebuilds/verifies it from pledgePayments for drift\n// repair. Shape mirrors the PledgePaymentTotals view-model + updatedAt.\nexport const PledgePaymentTotalsDocSchema = z.object({\n netRaised: z.number(),\n grossRaised: z.number(),\n totalRefunded: z.number(),\n pledgeCount: z.number(),\n updatedAt: z.number(),\n});\nexport type PledgePaymentTotalsDoc = z.infer<typeof PledgePaymentTotalsDocSchema>;\n\n// processedStripeEvents/{stripeEventId} — idempotency sentinel, one doc per processed Stripe\n// event.id, kept forever. Checked + written in the same transaction as the side effect so a\n// redelivered event (completion, expiry, failure, or quarantine) produces no duplicate.\n// pledgePaymentId is set only when the event created a pledge. (runProcessStripePledgeEvent.ts)\nexport const ProcessedStripeEventSchema = z.object({\n eventId: z.string(),\n eventType: z.string(),\n processedAt: z.number(),\n pledgePaymentId: z.string().nullable(),\n});\nexport type ProcessedStripeEvent = z.infer<typeof ProcessedStripeEventSchema>;\n\n// pledgePaymentLedgerEvents/{ledgerId} — independent integrity record from the onPledgePaymentWritten\n// trigger (mirrors stakeShareAuditEvents). before/after are raw doc snapshots (null on create/delete)\n// kept as permissive bags so a malformed/anomalous write is still captured forensically.\n// (functions/src/audit/runPledgePaymentLedgerAudit.ts)\nexport const PledgePaymentLedgerEventSchema = z.object({\n ledgerId: z.string(),\n pledgePaymentId: z.string(),\n subtype: z.string(), // e.g. 'created' | 'anomaly'\n reason: z.string(),\n before: z.record(z.string(), z.unknown()).nullable(),\n after: z.record(z.string(), z.unknown()).nullable(),\n source: z.literal('firestore-trigger'),\n createdAt: z.number(),\n});\nexport type PledgePaymentLedgerEvent = z.infer<typeof PledgePaymentLedgerEventSchema>;\n\n// paymentWebhookQuarantine/{stripeEventId} — admin-readable repair queue for paid-but-malformed\n// events (e.g. missing metadata) that must NOT make Stripe retry. Redaction rule: never store raw\n// payloads, card/billing data, customer email, addresses, or receipt URLs — IDs + a short redacted\n// rawSafeSummary only. (functions/src/payments/runProcessStripePledgeEvent.ts)\nexport const PaymentWebhookQuarantineSchema = z.object({\n eventId: z.string(),\n eventType: z.string(),\n livemode: z.boolean(),\n reason: z.string(),\n recoverable: z.boolean(),\n stripeObjectIds: z.object({\n sessionId: z.string().optional(),\n paymentIntentId: z.string().optional(),\n chargeId: z.string().optional(),\n }),\n pledgePaymentId: z.string().optional(),\n userId: z.string().optional(),\n amount: z.number().optional(),\n currency: z.string().optional(),\n rawSafeSummary: z.string(),\n status: z.enum(['open', 'resolved', 'ignored']),\n adminTaskId: z.string().optional(),\n createdAt: z.number(),\n resolvedAt: z.number().optional(),\n resolvedBy: z.string().optional(),\n resolutionNote: z.string().optional(),\n});\nexport type PaymentWebhookQuarantine = z.infer<typeof PaymentWebhookQuarantineSchema>;\n\n// pledgeRefundRequests/{requestId} — a supporter's pledge refund request. Lifecycle: requested →\n// (admin approves) approving → initiated → completed, or → failed when Stripe reports the refund\n// failed, which raises a pledgeRefundFailed admin task; requested → denied by an admin. A full refund of the pledge from anywhere, the Stripe\n// Dashboard included, completes an open request. NO Stripe ids on this doc — they live on\n// pledgePaymentProviderRefs. Server-only writes. Timestamps are epoch-millis numbers.\nexport const PLEDGE_REFUND_REQUEST_STATUSES = [\n 'requested',\n 'approving',\n 'initiated',\n 'denied',\n 'completed',\n 'failed',\n] as const;\nexport const PledgeRefundRequestStatusSchema = z.enum(PLEDGE_REFUND_REQUEST_STATUSES);\nexport type PledgeRefundRequestStatus = z.infer<typeof PledgeRefundRequestStatusSchema>;\n\n/** The statuses of a request in flight. A failed request is open too until its follow-up is resolved. */\nexport const PLEDGE_REFUND_OPEN_STATUSES = [\n 'requested',\n 'approving',\n 'initiated',\n] as const satisfies readonly PledgeRefundRequestStatus[];\n\n/**\n * Whether a request still blocks a new one for its pledge (a pledge has at most one open request):\n * in flight, or failed while an admin is still following the failure up — the supporter may not\n * ask again until that follow-up is resolved.\n */\nexport function isPledgeRefundRequestOpen(\n request: Pick<PledgeRefundRequest, 'status' | 'failureFollowUpResolvedAt'>,\n): boolean {\n if (request.status === 'failed') return request.failureFollowUpResolvedAt === undefined;\n return (PLEDGE_REFUND_OPEN_STATUSES as readonly PledgeRefundRequestStatus[]).includes(request.status);\n}\n\nexport const PledgeRefundRequestSchema = z.object({\n pledgePaymentId: z.string(),\n userId: z.string(),\n amount: z.number(),\n status: PledgeRefundRequestStatusSchema,\n reason: z.string().optional(), // the requester's stated reason\n denialReason: z.string().optional(), // set when an admin denies\n resolvedBy: z.string().optional(), // admin uid who approved/denied\n requestedAt: z.number(),\n resolvedAt: z.number().optional(),\n approvingAt: z.number().optional(), // when an admin's approval began, before Stripe was called\n completedAt: z.number().optional(),\n failedAt: z.number().optional(), // when Stripe reported the refund failed\n // When an admin resolved the failed refund's follow-up task (the refund decision that closes it).\n // Only a failed request carries it; until it is set, the failed request keeps its pledge open.\n failureFollowUpResolvedAt: z.number().optional(),\n}).superRefine((val, ctx) => {\n if (val.failureFollowUpResolvedAt !== undefined && val.status !== 'failed') {\n ctx.addIssue({ code: 'custom', path: ['failureFollowUpResolvedAt'] });\n }\n});\nexport type PledgeRefundRequest = z.infer<typeof PledgeRefundRequestSchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"payments.js","sourceRoot":"","sources":["../../src/doc-schemas/payments.ts"],"names":[],"mappings":"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","sourcesContent":["// Payment / pledge Firestore document SCHEMAS — the public-safe pledge ledger and its\n// server-only companions: provider refs (Stripe IDs), the idempotency sentinel, the\n// independent integrity trail, and the paid-event quarantine queue. Types inferred via\n// z.infer. Money data lives here, never in social.ts.\n// See ttt-prod docs/design/donation-payment-system.md (the design owner for the\n// pledge/Stripe flow).\n\nimport { z } from 'zod';\nimport { LegalReviewNoticeReceiptSchema } from './legal-review-notice.js';\nimport { MAX_INTERNAL_REASON_LENGTH } from '../constants/business-admin.js';\n\n/** How much of a pledge has been refunded: `partial` while some net remains, `full` once none does. */\nexport const PLEDGE_REFUND_STATES = ['none', 'partial', 'full'] as const;\nexport const PledgeRefundStateSchema = z.enum(PLEDGE_REFUND_STATES);\nexport type PledgeRefundState = z.infer<typeof PledgeRefundStateSchema>;\n\n/** Where a chargeback dispute stands: `underReview` while open, then `won` or `lost` once closed. */\nexport const PLEDGE_DISPUTE_STATES = ['none', 'underReview', 'won', 'lost'] as const;\nexport const PledgeDisputeStateSchema = z.enum(PLEDGE_DISPUTE_STATES);\nexport type PledgeDisputeState = z.infer<typeof PledgeDisputeStateSchema>;\n\nconst PLEDGE_DISPUTE_STATE_RANK: Record<PledgeDisputeState, number> = {\n none: 0,\n underReview: 1,\n won: 2,\n lost: 2,\n};\n\n/** A dispute state's place on the one-way ladder none < underReview < won | lost. */\nexport function pledgeDisputeStateRank(state: PledgeDisputeState): number {\n return PLEDGE_DISPUTE_STATE_RANK[state];\n}\n\n/**\n * Whether moving ONE dispute from `from` to `to` goes up the ladder. Stripe can deliver a\n * dispute's events late or twice, so within one dispute a closed dispute never reopens to\n * `underReview`, and `won` and `lost` never replace each other.\n */\nexport function isPledgeDisputeAdvance(from: PledgeDisputeState, to: PledgeDisputeState): boolean {\n return pledgeDisputeStateRank(to) > pledgeDisputeStateRank(from);\n}\n\n/**\n * Whether a dispute event may set the pledge's dispute state. The ladder holds per dispute: an\n * event for a different dispute than the recorded `disputeId` (the first one, or a later dispute\n * on the same charge) starts its own ladder, and an event for the recorded dispute applies only as\n * an advance. Ordering across disputes is the observation stamp's job — the handler first refuses\n * an event no newer than `disputeObservedAt`, so a late event of an earlier dispute never lands.\n */\nexport function isPledgeDisputeEventApplicable(\n recorded: { disputeId: string | null; state: PledgeDisputeState },\n event: { disputeId: string; state: PledgeDisputeState },\n): boolean {\n if (recorded.disputeId !== event.disputeId) return true;\n return isPledgeDisputeAdvance(recorded.state, event.state);\n}\n\n/**\n * The pledge's dispute number for a dispute event: the recorded number while the event is about the\n * recorded dispute (the provider ref's `disputeId`), one more for any other dispute — so the first\n * dispute is 1 and each later one adds one. The number is what the member-readable pledge carries in\n * place of Stripe's dispute id, which stays on the server-only provider ref.\n */\nexport function pledgeDisputeNumberForEvent(\n recorded: { disputeId: string | null; disputeNumber: number },\n eventDisputeId: string,\n): number {\n return recorded.disputeId === eventDisputeId ? recorded.disputeNumber : recorded.disputeNumber + 1;\n}\n\n/**\n * Whether a pledge's dispute fields may move from `before` to `after` — the rule an integrity check\n * reads from the pledge alone. Under the same dispute number the state only climbs the ladder (or stays,\n * as a redelivery or a refund leaves it); a number one higher is a new dispute, which starts its own\n * ladder at any state but `none` (its close may arrive before its opening). Any other number change is\n * not a legal transition.\n */\nexport function isPledgeDisputeTransitionLegal(\n before: { disputeNumber: number; disputeState: PledgeDisputeState },\n after: { disputeNumber: number; disputeState: PledgeDisputeState },\n): boolean {\n if (after.disputeNumber === before.disputeNumber) {\n return after.disputeState === before.disputeState || isPledgeDisputeAdvance(before.disputeState, after.disputeState);\n }\n if (after.disputeNumber === before.disputeNumber + 1) return after.disputeState !== 'none';\n return false;\n}\n\n// pledgePayments/{pledgePaymentId} — public-safe canonical money record. One doc per completed\n// pledge; never deleted/archived. No Stripe IDs, no supporter message. Auth-readable; server-only\n// writes, by the Stripe webhook alone. netAmount = max(0, amount - refundedAmount - disputeLostAmount)\n// is the sum() target; the refund and dispute handlers recompute it from Stripe's totals.\nexport const PledgePaymentSchema = z.object({\n pledgePaymentId: z.string(),\n userId: z.string(),\n amount: z.number(), // gross cents charged (Stripe-confirmed amount_total)\n refundedAmount: z.number(), // cumulative refunded cents, from the Charge's amount_refunded; 0 on a new pledge\n disputeLostAmount: z.number(), // cents withdrawn on a lost dispute; 0 otherwise\n netAmount: z.number(), // max(0, amount - refundedAmount - disputeLostAmount); sum() target\n currency: z.string(), // \"usd\"\n paymentInstrument: z.literal('card'),\n status: z.literal('completed'),\n refundState: PledgeRefundStateSchema,\n disputeState: PledgeDisputeStateSchema,\n // How many disputes the pledge has had: 0 until the first, then 1, 2, … (pledgeDisputeNumberForEvent).\n // It tells one dispute from the next on this member-readable doc; Stripe's dispute id stays on the\n // server-only provider ref.\n disputeNumber: z.number().int().nonnegative(),\n // NO ageAttestedAt here: age-attestation evidence is server-only and lives on\n // PledgePaymentProviderRefSchema. This doc is auth-readable by every signed-in member.\n createdAt: z.number(),\n updatedAt: z.number(),\n}).superRefine((val, ctx) => {\n if ((val.disputeNumber === 0) !== (val.disputeState === 'none')) {\n ctx.addIssue({ code: 'custom', path: ['disputeNumber'] });\n }\n});\nexport type PledgePayment = z.infer<typeof PledgePaymentSchema>;\n\n// pledgePaymentProviderRefs/{pledgePaymentId} — server-only Stripe references for reconciliation\n// and refund/dispute lookup, PLUS the age-attestation consent evidence. Rule is permanently\n// `if false` (Admin SDK only) so no Stripe IDs ever sit on an auth-readable doc. One doc per pledge\n// (singular).\nexport const PledgePaymentProviderRefSchema = z.object({\n pledgePaymentId: z.string(),\n userId: z.string(),\n stripeSessionId: z.string(),\n paymentIntentId: z.string(),\n latestChargeId: z.string().nullable(), // resolved when known; null at launch if not fetched\n refundIds: z.array(z.string()), // every Stripe refund id seen on the charge; [] on a new pledge\n disputeId: z.string().nullable(), // the dispute the ledger's disputeState describes (the latest opened), null until one opens\n // Server timestamp (ms) of the checkout's 18+/public-disclosure attestation, stamped at session\n // creation and carried through Stripe metadata. A paid session missing it is quarantined. It is\n // fraud-evidence plumbing, not transparency data, so it rides THIS server-only doc and never the\n // member-readable pledgePayments ledger (docs/design/donation-payment-system.md § Data model).\n ageAttestedAt: z.number(),\n // The founder legal-review notice acknowledgment given at checkout (its own required checkbox\n // on every pledge while the notice is active): the revision and server time, stamped at session\n // creation and carried through the Stripe metadata like `ageAttestedAt`. Absent when the notice\n // was off. Evidence, not transparency data — it rides this server-only doc only.\n legalReviewNotice: LegalReviewNoticeReceiptSchema.optional(),\n // The refund an approval asks Stripe for: written in the transaction that moves its request to\n // `approving` (before Stripe is called), `refundId` stamped once Stripe answers, removed when the\n // request reaches `completed` or `failed`. A request is finished only by a refund matching it.\n refundCorrelation: z\n .object({\n requestId: z.string().min(1),\n intendedAmount: z.number().int().positive(),\n refundId: z.string().min(1).optional(),\n })\n .optional(),\n // The Stripe event time (epoch ms) the refund handler and the dispute handler last applied. Stripe\n // can deliver events out of order, so each handler applies an event only when it is newer.\n refundObservedAt: z.number().optional(),\n disputeObservedAt: z.number().optional(),\n // Stripe's reason for the last failed refund, kept server-side for the admin following up.\n lastRefundFailureReason: z.string().max(MAX_INTERNAL_REASON_LENGTH).optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n});\nexport type PledgePaymentProviderRef = z.infer<typeof PledgePaymentProviderRefSchema>;\n\n// pledgePaymentTotals/summary — the stored running-totals singleton behind every \"total raised\"\n// surface. Incremented via FieldValue.increment INSIDE the Stripe webhook's pledge-record\n// transaction (same commit as the pledgePayments doc — the two can never drift on a completed\n// pledge); the refund and dispute handlers adjust it in the transaction that changes the pledge,\n// through pledgePaymentTotalsOf (utils/pledge-totals). Auth-readable, server-only\n// writes. An idempotent recompute script rebuilds/verifies it from pledgePayments for drift\n// repair. Shape mirrors the PledgePaymentTotals view-model + updatedAt.\nexport const PledgePaymentTotalsDocSchema = z.object({\n netRaised: z.number(),\n grossRaised: z.number(),\n totalRefunded: z.number(),\n pledgeCount: z.number(),\n updatedAt: z.number(),\n});\nexport type PledgePaymentTotalsDoc = z.infer<typeof PledgePaymentTotalsDocSchema>;\n\n// processedStripeEvents/{stripeEventId} — idempotency sentinel, one doc per processed Stripe\n// event.id, kept forever. Checked + written in the same transaction as the side effect so a\n// redelivered event (completion, expiry, failure, or quarantine) produces no duplicate.\n// pledgePaymentId is set only when the event created a pledge. (runProcessStripePledgeEvent.ts)\nexport const ProcessedStripeEventSchema = z.object({\n eventId: z.string(),\n eventType: z.string(),\n processedAt: z.number(),\n pledgePaymentId: z.string().nullable(),\n});\nexport type ProcessedStripeEvent = z.infer<typeof ProcessedStripeEventSchema>;\n\n// pledgePaymentLedgerEvents/{ledgerId} — independent integrity record from the onPledgePaymentWritten\n// trigger (mirrors stakeShareAuditEvents). before/after are raw doc snapshots (null on create/delete)\n// kept as permissive bags so a malformed/anomalous write is still captured forensically.\n// (functions/src/audit/runPledgePaymentLedgerAudit.ts)\nexport const PledgePaymentLedgerEventSchema = z.object({\n ledgerId: z.string(),\n pledgePaymentId: z.string(),\n subtype: z.string(), // e.g. 'created' | 'anomaly'\n reason: z.string(),\n before: z.record(z.string(), z.unknown()).nullable(),\n after: z.record(z.string(), z.unknown()).nullable(),\n source: z.literal('firestore-trigger'),\n createdAt: z.number(),\n});\nexport type PledgePaymentLedgerEvent = z.infer<typeof PledgePaymentLedgerEventSchema>;\n\n// paymentWebhookQuarantine/{stripeEventId} — admin-readable repair queue for paid-but-malformed\n// events (e.g. missing metadata) that must NOT make Stripe retry. Redaction rule: never store raw\n// payloads, card/billing data, customer email, addresses, or receipt URLs — IDs + a short redacted\n// rawSafeSummary only. (functions/src/payments/runProcessStripePledgeEvent.ts)\nexport const PaymentWebhookQuarantineSchema = z.object({\n eventId: z.string(),\n eventType: z.string(),\n livemode: z.boolean(),\n reason: z.string(),\n recoverable: z.boolean(),\n stripeObjectIds: z.object({\n sessionId: z.string().optional(),\n paymentIntentId: z.string().optional(),\n chargeId: z.string().optional(),\n }),\n pledgePaymentId: z.string().optional(),\n userId: z.string().optional(),\n amount: z.number().optional(),\n currency: z.string().optional(),\n rawSafeSummary: z.string(),\n status: z.enum(['open', 'resolved', 'ignored']),\n adminTaskId: z.string().optional(),\n createdAt: z.number(),\n resolvedAt: z.number().optional(),\n resolvedBy: z.string().optional(),\n resolutionNote: z.string().optional(),\n});\nexport type PaymentWebhookQuarantine = z.infer<typeof PaymentWebhookQuarantineSchema>;\n\n// pledgeRefundRequests/{requestId} — a supporter's pledge refund request. Lifecycle: requested →\n// (admin approves) approving → initiated → completed, or → failed when Stripe reports the refund\n// failed, which raises a pledgeRefundFailed admin task; requested → denied by an admin. A full refund of the pledge from anywhere, the Stripe\n// Dashboard included, completes an open request. NO Stripe ids on this doc — they live on\n// pledgePaymentProviderRefs. Server-only writes. Timestamps are epoch-millis numbers.\nexport const PLEDGE_REFUND_REQUEST_STATUSES = [\n 'requested',\n 'approving',\n 'initiated',\n 'denied',\n 'completed',\n 'failed',\n] as const;\nexport const PledgeRefundRequestStatusSchema = z.enum(PLEDGE_REFUND_REQUEST_STATUSES);\nexport type PledgeRefundRequestStatus = z.infer<typeof PledgeRefundRequestStatusSchema>;\n\n/** The statuses of a request in flight. A failed request is open too until its follow-up is resolved. */\nexport const PLEDGE_REFUND_OPEN_STATUSES = [\n 'requested',\n 'approving',\n 'initiated',\n] as const satisfies readonly PledgeRefundRequestStatus[];\n\n/**\n * Whether a request still blocks a new one for its pledge (a pledge has at most one open request):\n * in flight, or failed while an admin is still following the failure up — the supporter may not\n * ask again until that follow-up is resolved.\n */\nexport function isPledgeRefundRequestOpen(\n request: Pick<PledgeRefundRequest, 'status' | 'failureFollowUpResolvedAt'>,\n): boolean {\n if (request.status === 'failed') return request.failureFollowUpResolvedAt === undefined;\n return (PLEDGE_REFUND_OPEN_STATUSES as readonly PledgeRefundRequestStatus[]).includes(request.status);\n}\n\nexport const PledgeRefundRequestSchema = z.object({\n pledgePaymentId: z.string(),\n userId: z.string(),\n amount: z.number(),\n status: PledgeRefundRequestStatusSchema,\n reason: z.string().optional(), // the requester's stated reason\n denialReason: z.string().optional(), // set when an admin denies\n resolvedBy: z.string().optional(), // admin uid who approved/denied\n requestedAt: z.number(),\n resolvedAt: z.number().optional(),\n approvingAt: z.number().optional(), // when an admin's approval began, before Stripe was called\n completedAt: z.number().optional(),\n failedAt: z.number().optional(), // when Stripe reported the refund failed\n // When an admin resolved the failed refund's follow-up task (the refund decision that closes it).\n // Only a failed request carries it; until it is set, the failed request keeps its pledge open.\n failureFollowUpResolvedAt: z.number().optional(),\n}).superRefine((val, ctx) => {\n if (val.failureFollowUpResolvedAt !== undefined && val.status !== 'failed') {\n ctx.addIssue({ code: 'custom', path: ['failureFollowUpResolvedAt'] });\n }\n});\nexport type PledgeRefundRequest = z.infer<typeof PledgeRefundRequestSchema>;\n"]}
|