@ttt-productions/ttt-core 0.78.20 → 0.78.22
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/admin-labels.d.ts +1 -1
- package/dist/constants/admin-labels.js +2 -2
- package/dist/constants/admin-labels.js.map +1 -1
- package/dist/constants/center-stage-rooms.js +1 -1
- package/dist/constants/center-stage-rooms.js.map +1 -1
- package/dist/constants/company-mascots.js +1 -1
- package/dist/constants/company-mascots.js.map +1 -1
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +1 -0
- package/dist/constants/index.js.map +1 -1
- package/dist/constants/media-processing.d.ts +13 -0
- package/dist/constants/media-processing.d.ts.map +1 -0
- package/dist/constants/media-processing.js +18 -0
- package/dist/constants/media-processing.js.map +1 -0
- package/dist/constants/publish-attestations.js +1 -1
- package/dist/constants/publish-attestations.js.map +1 -1
- package/dist/constants/safety-confirmation-phrases.js +1 -1
- package/dist/constants/safety-confirmation-phrases.js.map +1 -1
- package/dist/doc-schemas/account-deletion.js +1 -1
- package/dist/doc-schemas/account-deletion.js.map +1 -1
- package/dist/doc-schemas/moderation.d.ts +2 -0
- package/dist/doc-schemas/moderation.d.ts.map +1 -1
- package/dist/doc-schemas/registry.d.ts +18 -0
- package/dist/doc-schemas/registry.d.ts.map +1 -1
- package/dist/doc-schemas/registry.js +1 -1
- package/dist/doc-schemas/registry.js.map +1 -1
- package/dist/doc-schemas/safety/age.js +1 -1
- package/dist/doc-schemas/safety/age.js.map +1 -1
- package/dist/doc-schemas/safety/evidence.js +1 -1
- package/dist/doc-schemas/safety/evidence.js.map +1 -1
- package/dist/doc-schemas/safety/foundation.d.ts +3 -3
- package/dist/doc-schemas/safety/foundation.d.ts.map +1 -1
- package/dist/doc-schemas/safety/foundation.js +3 -3
- package/dist/doc-schemas/safety/foundation.js.map +1 -1
- package/dist/doc-schemas/square-announcement-jobs.d.ts +1 -1
- package/dist/doc-schemas/square-announcement-jobs.js +2 -2
- package/dist/doc-schemas/square-announcement-jobs.js.map +1 -1
- package/dist/media/pending-media.d.ts +32 -0
- package/dist/media/pending-media.d.ts.map +1 -1
- package/dist/media/target-info.js +1 -1
- package/dist/media/target-info.js.map +1 -1
- package/dist/paths/collections.js +2 -2
- package/dist/paths/collections.js.map +1 -1
- package/dist/paths/path-builders.js +1 -1
- package/dist/paths/path-builders.js.map +1 -1
- package/dist/paths/related-ids.js +1 -1
- package/dist/paths/related-ids.js.map +1 -1
- package/dist/safety/active-safety-case-alert.js +1 -1
- package/dist/safety/active-safety-case-alert.js.map +1 -1
- package/dist/safety/ncii-intake-derivations.js +1 -1
- package/dist/safety/ncii-intake-derivations.js.map +1 -1
- package/dist/safety/resource-keys.js +1 -1
- package/dist/safety/resource-keys.js.map +1 -1
- package/dist/schemas/chat.js +1 -1
- package/dist/schemas/chat.js.map +1 -1
- package/dist/schemas/craft-skills.js +1 -1
- package/dist/schemas/craft-skills.js.map +1 -1
- package/dist/schemas/hall-library.js +1 -1
- package/dist/schemas/hall-library.js.map +1 -1
- package/dist/schemas/notification.js +1 -1
- package/dist/schemas/notification.js.map +1 -1
- package/dist/schemas/safety.d.ts +1 -1
- package/dist/schemas/safety.js +1 -1
- package/dist/schemas/safety.js.map +1 -1
- package/dist/types/admin-ops.d.ts +1 -1
- package/dist/types/admin-ops.d.ts.map +1 -1
- package/dist/types/admin-ops.js +1 -1
- package/dist/types/admin-ops.js.map +1 -1
- package/dist/types/admin-users.js +1 -1
- package/dist/types/admin-users.js.map +1 -1
- package/dist/types/social.d.ts +1 -1
- package/dist/types/social.js.map +1 -1
- package/dist/upload-variables/create-admin-audition-variables.js +1 -1
- package/dist/upload-variables/create-admin-audition-variables.js.map +1 -1
- package/dist/upload-variables/create-work-project-audition-variables.js +1 -1
- package/dist/upload-variables/create-work-project-audition-variables.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/doc-schemas/registry.ts"],"names":[],"mappings":"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","sourcesContent":["// Firestore collection registry — the single, authoritative binding from each Firestore\n// collection/subcollection path template to its document Zod schema. This is the input to\n// the schema-doc generator and the drift-check, and its completeness is CI-enforced\n// (registry.test.ts) against the COLLECTIONS / *_SUBCOLLECTIONS name constants, so a new\n// collection cannot be added without either a schema or an explicit PENDING entry.\n//\n// Path templates reuse the segment names from ../paths/collections.ts (and the shapes the\n// path-builders produce). `{placeholder}` segments are document/parent IDs.\n\nimport type { z } from 'zod';\nimport {\n FullUserSchema,\n UserPrivateDataSchema,\n CraftSkillSchema,\n CraftSkillReferenceSchema,\n} from './user.js';\nimport { PublicUserSchema } from './publicUser.js';\nimport { AccountDeletionRequestV1Schema } from './account-deletion.js';\nimport {\n FullWorkProjectSchema,\n PublicWorkProjectSchema,\n WorkFileFolderSchema,\n WorkFileSchema,\n WorkRealmSchema,\n GuildmateUserSchema,\n PublicGuildmateUserSchema,\n} from './work-project.js';\nimport {\n FullTaleSchema,\n FullChapterSchema,\n FullTuneSchema,\n FullTuneTrackSchema,\n FullTelevisionSchema,\n FullTelevisionEpisodeSchema,\n ThresholdItemSchema,\n PublishedHallItemSchema,\n PublishedChapterSchema,\n PublishedTuneTrackSchema,\n PublishedTelevisionEpisodeSchema,\n HallContentChangeRequestSchema,\n FuturePlansDocumentSchema,\n RulesAndAgreementsSchema,\n LegalPageDocumentSchema,\n TakeItDownPageCopySchema,\n HallLibraryPreferencesSchema,\n} from './content.js';\nimport {\n SquareStreetzPostSchema,\n MentionHistoryDocumentSchema,\n FollowEdgeSchema,\n FollowCounterSchema,\n SquareStreetzLikeSchema,\n TrendingPostsSchema,\n} from './social.js';\nimport {\n PledgePaymentSchema,\n PledgePaymentProviderRefSchema,\n ProcessedStripeEventSchema,\n PledgePaymentLedgerEventSchema,\n PaymentWebhookQuarantineSchema,\n PledgePaymentTotalsDocSchema,\n PledgeRefundRequestSchema,\n} from './payments.js';\nimport {\n FullCommissionListingSchema,\n CommissionProposalSchema,\n AuditionSchema,\n AuditionEntrySchema,\n UserAuditionVoteSchema,\n} from './commissions.js';\nimport {\n GuildChatChannelSchema,\n GuildInviteConversationSchema,\n AdminDispatchSchema,\n ChatMessageV1Schema,\n} from './messaging.js';\nimport { AppConfigSchema, AdminListSchema, ProfanityListSchema, ReservedUsernamesSchema, BlockedFranchiseNamesSchema, AppModeMarkerSchema } from './system.js';\nimport {\n ContentViolationSchema,\n ModerationCascadeManifestSchema,\n ModerationCascadeChangedDocSchema,\n} from './moderation.js';\nimport {\n AdminTaskDocSchema,\n} from './report-docs.js';\nimport { TTTAuditEventSchema } from './audit.js';\nimport {\n NotificationDocSchema,\n NotificationHistoryDocSchema,\n PendingNotificationSchema,\n} from './notifications.js';\nimport {\n NotificationDeliverySchema,\n NotificationFanoutJobSchema,\n} from './notification-ledger.js';\nimport {\n ChatChannelAuthProjectionSchema,\n ChatScopeDegradedSchema,\n ChatScopeDegradedCauseSchema,\n ChatSyncEventSchema,\n ChatSyncFanoutJobSchema,\n ChatMessageOutboxSchema,\n ChatAdminActionCommandSchema,\n ChatHistoryAnonymizationJobSchema,\n ChatHistoryAnonymizationAffectedChunkSchema,\n} from './chat-sync.js';\nimport { SquareAnnouncementJobSchema } from './square-announcement-jobs.js';\nimport { PendingMediaSchema, ArchivedPendingMediaSchema } from '../media/pending-media.js';\nimport { MediaAssetSchema } from './media-assets.js';\nimport { MediaActivationJobSchema } from './media-activation-jobs.js';\nimport {\n ReservedDisplayNameSchema,\n ReservedRealmNameSchema,\n StakeShareAuditEventSchema,\n ShortLinkSchema,\n FeedbackAliasSchema,\n UserSuggestionSchema,\n StatusReconcileQueueEntrySchema,\n} from './operational.js';\n// ===== Trust & Safety — report spine (§A1) =====\nimport {\n ProtectedReportRootV1Schema,\n ReportPublicProjectionV1Schema,\n ReportGroupV1Schema,\n ReportTargetSnapshotV1Schema,\n NarrativeRecordV1Schema,\n} from './safety/report.js';\nimport { SafetyCaseAlertV1Schema } from './safety/case-alert.js';\n// ===== Trust & Safety — child-safety case spine (§A1b, §A2) =====\nimport {\n ChildSafetyCaseListV1Schema,\n ChildSafetyCaseV1Schema,\n ChildSafetySourceSignalV1Schema,\n ChildSafetyDecisionV1Schema,\n ChildSafetyDecisionViewV1Schema,\n ChildSafetyCaseAccountV1Schema,\n ChildSafetyCaseAccountHistoryV1Schema,\n ChildSafetyNcmecSubmissionV1Schema,\n ChildSafetyNcmecSubmissionFileV1Schema,\n ChildSafetyLegalProcessEventV1Schema,\n} from './safety/case.js';\nimport {\n ChildSafetyOwningAliasV1Schema,\n} from './safety/case-aliases.js';\nimport {\n SafetyHoldRefV1Schema,\n SafetyHoldResourceV1Schema,\n SafetyResourceCommandV1Schema,\n SafetyResourceCommandAuthorizedRequestV1Schema,\n SafetyResourceCommandBypassRefV1Schema,\n} from './safety/holds.js';\nimport {\n SafetyEvidenceManifestV1Schema,\n SafetyEvidenceJobV1Schema,\n SafetyEvidenceJobItemV1Schema,\n SafetyEvidenceDispositionV1Schema,\n} from './safety/evidence.js';\nimport { EventProvenanceV1Schema } from './safety/provenance.js';\nimport {\n QuarantineSagaJobV1Schema,\n QuarantineSagaRelatedAssetV1Schema,\n NcmecSubmissionJobV1Schema,\n AccountActionCommandV1Schema,\n} from './safety/sagas.js';\nimport {\n SafetySlaMonitorV1Schema,\n SafetyMonitorHeartbeatV1Schema,\n} from './safety/monitors.js';\nimport { AgeAttestationNonceV1Schema, AgePolicyConfigV1Schema } from './safety/age.js';\nimport {\n PrivilegedReviewerPasskeyProfileV1Schema,\n PrivilegedReviewerCapabilityGrantV1Schema,\n} from './safety/reviewer-security.js';\n// ===== Trust & Safety — NCII / TAKE IT DOWN (§A11) =====\nimport { NciiAllegationV1Schema } from './ncii/allegations.js';\nimport {\n TakeItDownRequestRootV1Schema,\n TakeItDownRequesterPrivateV1Schema,\n TakeItDownSubmissionV1Schema,\n TakeItDownValidityDecisionV1Schema,\n TakeItDownRequestActionV1Schema,\n TakeItDownEvidenceV1Schema,\n NciiRetainedEvidenceInventoryV1Schema,\n} from './ncii/requests.js';\nimport {\n NciiCaseV1Schema,\n NciiCaseAllegationLinkV1Schema,\n NciiCaseRequestLinkV1Schema,\n NciiCaseRemovalActionV1Schema,\n NciiBlockedHashV1Schema,\n} from './ncii/cases.js';\nimport { NciiTemporaryHoldV1Schema } from './ncii/holds.js';\nimport {\n NciiRemovalJobV1Schema,\n NciiRemovalTargetV1Schema,\n} from './ncii/removal.js';\nimport {\n NciiPolicyConfigV1Schema,\n PrivilegedReviewerSecurityProfileV1Schema,\n} from './ncii/config.js';\n\nexport const COLLECTION_SCHEMAS = {\n // ===== Users =====\n 'userProfiles/{userId}': FullUserSchema,\n 'userProfiles/{userId}/privateData/{userId}': UserPrivateDataSchema,\n 'userProfiles/{userId}/privateData/hallLibraryPreferences': HallLibraryPreferencesSchema,\n 'userProfiles/{userId}/profileCraftSkills/{craftSkillId}': CraftSkillSchema,\n 'userProfiles/{userId}/auditionVotes/{auditionId}': UserAuditionVoteSchema,\n 'userProfiles/{userId}/mentionHistory/{docId}': MentionHistoryDocumentSchema,\n 'userProfiles/{userId}/notificationHistory/{notificationId}': NotificationHistoryDocSchema,\n 'userProfiles/{userId}/userLikes/likeHistory/squareStreetzLikes/{postId}': SquareStreetzLikeSchema,\n 'publicUsers/{uid}': PublicUserSchema,\n\n // ===== Work / Realm / Guild =====\n 'allWorkProjects/{workProjectId}': FullWorkProjectSchema,\n 'allWorkProjects/{workProjectId}/guildmateUsers/{uid}': GuildmateUserSchema,\n 'allWorkProjects/{workProjectId}/publicGuildmateUsers/{uid}': PublicGuildmateUserSchema,\n 'allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}': WorkFileFolderSchema,\n 'allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}/workFiles/{workFileId}': WorkFileSchema,\n 'allWorkProjects/{workProjectId}/workProjectTales/{taleId}': FullTaleSchema,\n 'allWorkProjects/{workProjectId}/workProjectTales/{taleId}/taleChapters/{chapterId}': FullChapterSchema,\n 'allWorkProjects/{workProjectId}/workProjectTunes/{tuneId}': FullTuneSchema,\n 'allWorkProjects/{workProjectId}/workProjectTunes/{tuneId}/tuneTracks/{trackId}': FullTuneTrackSchema,\n 'allWorkProjects/{workProjectId}/workProjectTelevision/{televisionId}': FullTelevisionSchema,\n 'allWorkProjects/{workProjectId}/workProjectTelevision/{televisionId}/televisionEpisodes/{episodeId}': FullTelevisionEpisodeSchema,\n 'allWorkProjects/{workProjectId}/guildChatChannels/{guildChatChannelId}': GuildChatChannelSchema,\n // Guild channel + invite messages are REALTIME-ONLY (chat Worker DO) — no Firestore schema.\n 'publicWorkProjects/{workProjectId}': PublicWorkProjectSchema,\n 'workRealms/{workRealmId}': WorkRealmSchema,\n 'guildInviteConversations/{guildInviteId}': GuildInviteConversationSchema,\n\n // ===== Square / Social =====\n 'squareStreetzFeed/activePosts/socialPosts/{postId}': SquareStreetzPostSchema,\n 'squareStreetzFeed/trendingPosts': TrendingPostsSchema,\n 'followEdges/{followEdgeId}': FollowEdgeSchema,\n 'followCounters/{followCounterId}': FollowCounterSchema,\n // Durable Square announcement outbox (Admin-SDK-only; deterministic job ids).\n 'squareAnnouncementJobs/{jobId}': SquareAnnouncementJobSchema,\n\n // ===== Payments / pledge ledger =====\n 'pledgePayments/{pledgePaymentId}': PledgePaymentSchema,\n 'pledgePaymentProviderRefs/{pledgePaymentId}': PledgePaymentProviderRefSchema,\n 'processedStripeEvents/{stripeEventId}': ProcessedStripeEventSchema,\n 'pledgePaymentLedgerEvents/{ledgerId}': PledgePaymentLedgerEventSchema,\n 'paymentWebhookQuarantine/{stripeEventId}': PaymentWebhookQuarantineSchema,\n 'pledgePaymentTotals/summary': PledgePaymentTotalsDocSchema,\n 'pledgeRefundRequests/{requestId}': PledgeRefundRequestSchema,\n\n // ===== Threshold / Hall =====\n 'thresholdItems/{thresholdItemId}': ThresholdItemSchema,\n 'hallItems/{hallItemId}': PublishedHallItemSchema,\n // Published hall sub-item projections — the chapter/track/episode docs copied out of\n // the Work at publish time (runPublishApprovedHallLibraryItem). Segment names are the\n // HALL_ITEM_SUBCOLLECTIONS constants (the lowercased WorkProjectType).\n 'hallItems/{hallItemId}/tales/{itemId}': PublishedChapterSchema,\n 'hallItems/{hallItemId}/tunes/{itemId}': PublishedTuneTrackSchema,\n 'hallItems/{hallItemId}/television/{itemId}': PublishedTelevisionEpisodeSchema,\n 'hallContentChangeRequests/{changeRequestId}': HallContentChangeRequestSchema,\n\n // ===== Commission / Audition =====\n 'commissionListings/{commissionListingId}': FullCommissionListingSchema,\n 'commissionListings/{commissionListingId}/commissionProposals/{commissionProposalId}': CommissionProposalSchema,\n 'auditionBoard/{auditionId}': AuditionSchema,\n 'auditionBoard/{auditionId}/auditionEntries/{auditionEntryId}': AuditionEntrySchema,\n\n // ===== Moderation / Reports / Admin =====\n // The report spine (§A1): the restricted root, its public projection subdoc, and the\n // dedup/count group. The root + projection are written by the app's submitReport\n // callable; the group is maintained by an app-side trigger.\n 'contentReports/{reportId}': ProtectedReportRootV1Schema,\n 'contentReports/{reportId}/publicProjection/{reportId}': ReportPublicProjectionV1Schema,\n 'contentReports/{reportId}/private/snapshot': ReportTargetSnapshotV1Schema,\n 'contentReports/{reportId}/private/narrative': NarrativeRecordV1Schema,\n 'activeReportGroups/{groupKey}': ReportGroupV1Schema,\n 'adminTasks/{taskId}': AdminTaskDocSchema,\n 'contentViolations/{violationId}': ContentViolationSchema,\n 'moderationCascadeManifests/{cascadeId}': ModerationCascadeManifestSchema,\n 'moderationCascadeManifests/{cascadeId}/changedDocs/{changedDocId}': ModerationCascadeChangedDocSchema,\n 'auditEvents/{eventId}': TTTAuditEventSchema,\n 'stakeShareAuditEvents/{eventId}': StakeShareAuditEventSchema,\n 'pendingAdminDispatches/{adminDispatchId}': AdminDispatchSchema,\n 'pendingAdminDispatches/{adminDispatchId}/conversationMessages/{adminDispatchMessageId}': ChatMessageV1Schema,\n\n // ===== Media pipeline =====\n 'pendingMedia/{pendingMediaId}': PendingMediaSchema,\n 'pendingMediaArchive/{pendingMediaId}': ArchivedPendingMediaSchema,\n 'mediaAssets/{mediaAssetId}': MediaAssetSchema,\n 'mediaActivationJobs/{jobId}': MediaActivationJobSchema,\n\n // ===== Notifications =====\n 'activeUserNotifications/{notificationId}': NotificationDocSchema,\n 'activeAdminNotifications/{notificationId}': NotificationDocSchema,\n 'adminNotificationHistory/{notificationId}': NotificationHistoryDocSchema,\n 'pendingNotifications/{notificationId}': PendingNotificationSchema,\n\n // ===== Notification redesign — delivery ledger + fanout engine =====\n 'notificationDeliveries/{deliveryId}': NotificationDeliverySchema,\n 'notificationFanoutJobs/{jobId}': NotificationFanoutJobSchema,\n\n // ===== Chat realtime sync / projection / commands =====\n 'chatChannelAuthProjections/{authPairKey}': ChatChannelAuthProjectionSchema,\n 'chatScopeDegraded/{scopeKey}': ChatScopeDegradedSchema,\n 'chatScopeDegraded/{scopeKey}/causes/{causeId}': ChatScopeDegradedCauseSchema,\n 'chatSyncEvents/{eventId}': ChatSyncEventSchema,\n 'chatSyncFanoutJobs/{jobId}': ChatSyncFanoutJobSchema,\n 'chatMessageOutbox/{commandId}': ChatMessageOutboxSchema,\n 'chatAdminActionCommands/{requestId}': ChatAdminActionCommandSchema,\n 'chatHistoryAnonymizationJobs/{jobId}': ChatHistoryAnonymizationJobSchema,\n 'chatHistoryAnonymizationJobs/{jobId}/affectedChunks/{chunkOrdinal}': ChatHistoryAnonymizationAffectedChunkSchema,\n\n // ===== Craft skills index =====\n 'craftSkillsByTag/{tag}/taggedCraftSkills/{compositeId}': CraftSkillReferenceSchema,\n\n // ===== Operational / utility =====\n 'reservedDisplayNames/{displayNameUppercase}': ReservedDisplayNameSchema,\n 'reservedRealmNames/{workingTitleUppercase}': ReservedRealmNameSchema,\n 'accountDeletionRequests/{uid}': AccountDeletionRequestV1Schema,\n 'shortLinks/{shortId}': ShortLinkSchema,\n 'feedbackAliases/{aliasId}': FeedbackAliasSchema,\n 'feedbackSubmissions/{feedbackType}/userSuggestions/{suggestionId}': UserSuggestionSchema,\n 'statusReconcileQueue/{uid}': StatusReconcileQueueEntrySchema,\n\n // ===== Trust & Safety — child-safety case spine (§A1b, §A2) =====\n 'childSafetyCaseList/{caseId}': ChildSafetyCaseListV1Schema,\n 'activeSafetyCaseAlerts/{caseId}': SafetyCaseAlertV1Schema,\n 'childSafetyCases/{caseId}': ChildSafetyCaseV1Schema,\n 'childSafetyCases/{caseId}/sourceSignals/{signalId}': ChildSafetySourceSignalV1Schema,\n 'childSafetyCases/{caseId}/decisions/{decisionId}': ChildSafetyDecisionV1Schema,\n 'childSafetyCases/{caseId}/decisions/{decisionId}/views/{viewId}': ChildSafetyDecisionViewV1Schema,\n 'childSafetyCases/{caseId}/accounts/{uid}': ChildSafetyCaseAccountV1Schema,\n 'childSafetyCases/{caseId}/accounts/{uid}/history/{historyId}': ChildSafetyCaseAccountHistoryV1Schema,\n 'childSafetyCases/{caseId}/ncmecSubmissions/{submissionId}': ChildSafetyNcmecSubmissionV1Schema,\n 'childSafetyCases/{caseId}/ncmecSubmissions/{submissionId}/files/{fileId}': ChildSafetyNcmecSubmissionFileV1Schema,\n 'childSafetyCases/{caseId}/legalProcess/{eventId}': ChildSafetyLegalProcessEventV1Schema,\n 'childSafetyOwningAliases/{aliasId}': ChildSafetyOwningAliasV1Schema,\n\n // ===== Trust & Safety — holds + resource commands (§A3) =====\n 'safetyHoldRefs/{holdRefId}': SafetyHoldRefV1Schema,\n 'safetyHoldResources/{resourceKeyHash}': SafetyHoldResourceV1Schema,\n 'safetyResourceCommands/{commandDocId}': SafetyResourceCommandV1Schema,\n 'safetyResourceCommands/{commandDocId}/authorizedRequests/{requestId}': SafetyResourceCommandAuthorizedRequestV1Schema,\n 'safetyResourceCommands/{commandDocId}/bypassRefs/{refId}': SafetyResourceCommandBypassRefV1Schema,\n\n // ===== Trust & Safety — evidence + provenance (§A4, §A6) =====\n // SafetyEvidenceManifestV1Schema is a refined ZodObject (superRefine for the H5\n // sourceKind invariant); the schema-doc generator unwraps the effect to introspect\n // its shape, so binding the refined schema here is correct.\n 'safetyEvidenceManifests/{manifestId}': SafetyEvidenceManifestV1Schema,\n 'safetyEvidenceJobs/{jobId}': SafetyEvidenceJobV1Schema,\n 'safetyEvidenceJobs/{jobId}/items/{itemId}': SafetyEvidenceJobItemV1Schema,\n 'safetyEvidenceJobs/{jobId}/disposition/{locationId}': SafetyEvidenceDispositionV1Schema,\n 'eventProvenance/{eventId}': EventProvenanceV1Schema,\n\n // ===== Trust & Safety — sagas + closure (§A5) =====\n 'quarantineSagaJobs/{caseId}': QuarantineSagaJobV1Schema,\n 'quarantineSagaJobs/{caseId}/relatedAssets/{assetId}': QuarantineSagaRelatedAssetV1Schema,\n 'ncmecSubmissionJobs/{ncmecJobId}': NcmecSubmissionJobV1Schema,\n 'accountActionCommands/{accountActionCommandId}': AccountActionCommandV1Schema,\n\n // ===== Trust & Safety — SLA monitors + heartbeat (§A8) =====\n 'safetySlaMonitors/{monitorId}': SafetySlaMonitorV1Schema,\n 'safetyMonitorHeartbeat/global': SafetyMonitorHeartbeatV1Schema,\n\n // ===== Trust & Safety — age attestation nonces (§A7) =====\n 'ageAttestationNonces/{nonceHash}': AgeAttestationNonceV1Schema,\n\n // ===== Trust & Safety — per-operator privileged-reviewer security (§A11 [M-6] / [H-17]) =====\n // Backend-only (Cloud-Functions-only readers/writers; client access denied in firestore.rules).\n 'privilegedReviewerPasskeyProfiles/{uid}': PrivilegedReviewerPasskeyProfileV1Schema,\n 'privilegedReviewerCapabilityGrants/{uid}': PrivilegedReviewerCapabilityGrantV1Schema,\n\n // ===== Trust & Safety — NCII / TAKE IT DOWN (§A11) =====\n 'nciiAllegations/{allegationId}': NciiAllegationV1Schema,\n 'takeItDownRequests/{requestId}': TakeItDownRequestRootV1Schema,\n 'takeItDownRequests/{requestId}/private/requester': TakeItDownRequesterPrivateV1Schema,\n 'takeItDownRequests/{requestId}/submissions/{submissionId}': TakeItDownSubmissionV1Schema,\n 'takeItDownRequests/{requestId}/validityDecisions/{decisionId}': TakeItDownValidityDecisionV1Schema,\n 'takeItDownRequests/{requestId}/actions/{actionId}': TakeItDownRequestActionV1Schema,\n 'takeItDownRequests/{requestId}/evidence/{evidenceId}': TakeItDownEvidenceV1Schema,\n 'nciiCases/{caseId}': NciiCaseV1Schema,\n 'nciiCases/{caseId}/allegationLinks/{allegationId}': NciiCaseAllegationLinkV1Schema,\n 'nciiCases/{caseId}/requestLinks/{requestId}': NciiCaseRequestLinkV1Schema,\n 'nciiCases/{caseId}/removalActions/{actionId}': NciiCaseRemovalActionV1Schema,\n 'nciiCases/{caseId}/blockedHashes/{hashId}': NciiBlockedHashV1Schema,\n 'nciiRetainedEvidenceInventory/{inventoryId}': NciiRetainedEvidenceInventoryV1Schema,\n // [H-01] dead-letter sink for inventory rows that could not be written to the primary\n // nciiRetainedEvidenceInventory collection. Stores the same document shape.\n 'nciiInventoryDeadLetter/{inventoryId}': NciiRetainedEvidenceInventoryV1Schema,\n 'nciiTemporaryHolds/{holdId}': NciiTemporaryHoldV1Schema,\n 'nciiRemovalJobs/{jobId}': NciiRemovalJobV1Schema,\n 'nciiRemovalJobs/{jobId}/targets/{targetKeyHash}': NciiRemovalTargetV1Schema,\n\n // ===== _config singletons (public) =====\n '_config/app': AppConfigSchema,\n '_config/futurePlans': FuturePlansDocumentSchema,\n '_config/rulesAndAgreements': RulesAndAgreementsSchema,\n // Content-pages migration (DJ ruling 2026-07-06): /terms, /privacy, and the\n // /take-it-down page copy render exclusively from these (all public pages —\n // take-it-down is a NO-LOGIN page, so its copy doc must be publicly readable).\n '_config/termsOfService': LegalPageDocumentSchema,\n '_config/privacyPolicy': LegalPageDocumentSchema,\n '_config/takeItDownPageCopy': TakeItDownPageCopySchema,\n\n // ===== _serverData singletons (server-only — Cloud-Functions-only readers, Rule 32) =====\n '_serverData/agePolicy': AgePolicyConfigV1Schema,\n '_serverData/nciiPolicy': NciiPolicyConfigV1Schema,\n '_serverData/privilegedReviewerSecurity': PrivilegedReviewerSecurityProfileV1Schema,\n\n // ===== _systemData singletons =====\n '_systemData/adminList': AdminListSchema,\n '_systemData/profanityList': ProfanityListSchema,\n '_systemData/reservedUsernames': ReservedUsernamesSchema,\n '_systemData/blockedFranchiseNames': BlockedFranchiseNamesSchema,\n '_systemData/appMode': AppModeMarkerSchema,\n} as const satisfies Record<string, z.ZodTypeAny>;\n\nexport type RegisteredCollectionPath = keyof typeof COLLECTION_SCHEMAS;\n\n/**\n * Doc-id field annotation: for the listed bindings, the named body field equals the\n * Firestore document id and is injected at READ time (`{ ...doc.data(), <field>: doc.id }`),\n * never persisted — the write callables store the body via `Omit<…, '<field>'>`. The bound\n * schema models the (correct) consumer/read shape, where the field is required, so a raw\n * stored doc is \"missing\" it. The drift-check injects `{ [field]: doc.id, ...data }` before\n * validating, generalizing the one-off `AdminTaskDocSchema` stored-shape workaround into a\n * single mechanism so real-callable drift-checks don't false-flag every doc-id collection.\n * The schema-doc generator ignores this map. Keys are compiler-checked against the registry.\n */\nexport const COLLECTION_DOC_ID_FIELDS = {\n 'allWorkProjects/{workProjectId}/workProjectTales/{taleId}': 'uid',\n 'allWorkProjects/{workProjectId}/workProjectTales/{taleId}/taleChapters/{chapterId}': 'uid',\n 'allWorkProjects/{workProjectId}/workProjectTunes/{tuneId}': 'uid',\n 'allWorkProjects/{workProjectId}/workProjectTunes/{tuneId}/tuneTracks/{trackId}': 'uid',\n 'allWorkProjects/{workProjectId}/workProjectTelevision/{televisionId}': 'uid',\n 'allWorkProjects/{workProjectId}/workProjectTelevision/{televisionId}/televisionEpisodes/{episodeId}': 'uid',\n 'allWorkProjects/{workProjectId}/guildChatChannels/{guildChatChannelId}': 'guildChatChannelId',\n // Published hall sub-items: the doc id IS the live sub-item's id; `uid` is injected at\n // read (the publish writer spreads the live doc's stored body, which has no `uid`).\n 'hallItems/{hallItemId}/tales/{itemId}': 'uid',\n 'hallItems/{hallItemId}/tunes/{itemId}': 'uid',\n 'hallItems/{hallItemId}/television/{itemId}': 'uid',\n 'activeUserNotifications/{notificationId}': 'id',\n 'activeAdminNotifications/{notificationId}': 'id',\n 'adminNotificationHistory/{notificationId}': 'archiveOccurrenceId',\n 'userProfiles/{userId}/notificationHistory/{notificationId}': 'archiveOccurrenceId',\n 'pendingNotifications/{notificationId}': 'id',\n 'statusReconcileQueue/{uid}': 'uid',\n} as const satisfies Partial<Record<RegisteredCollectionPath, string>>;\n\n/**\n * Collections that exist (in COLLECTIONS / *_SUBCOLLECTIONS or firestore.rules) but are\n * intentionally NOT bound to a schema, each with a reason. Listed EXPLICITLY so completeness is\n * enforced and nothing is silently uncovered; the registry test fails if a NEW unlisted collection\n * appears. These three are the only remaining gaps after the schema-registry binding pass:\n *\n * - userMetadata: `userProfiles/{uid}/userMetadata/notificationSettings` — a firestore.rules\n * match and `PATH_BUILDERS.userMetadata` exist, but there is no live reader/writer and no\n * notification-settings type anywhere yet. Bind once that shape is implemented.\n * - checkedOutItems: a `userProfiles/{uid}/checkedOutItems` subcollection constant with no writer,\n * reader, rule, or path-builder (the admin \"checked out items\" UI reads adminTasks by\n * `checkoutDetails.userId`, not this subcollection). Vestigial — remove once confirmed safe.\n * - feedbackDenylist: `feedbackDenylist/{deniedWord}` — Console-managed (firestore.rules §3F: no\n * callable writes it) and submitFeedback reads it via `.exists` only, so there is no field\n * contract to author a schema from. The doc id is the denied word; the body is unused.\n */\nexport const PENDING_COLLECTIONS: readonly string[] = [\n 'userMetadata',\n 'checkedOutItems',\n 'feedbackDenylist',\n // Append-only NCII case closure/reopen event rows — the doc shape is owned app-side\n // (NciiCaseV1 closure events), not modeled in ttt-core doc-schemas.\n 'closureEvents',\n] as const;\n"]}
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/doc-schemas/registry.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,0FAA0F;AAC1F,oFAAoF;AACpF,yFAAyF;AACzF,mFAAmF;AACnF,EAAE;AACF,0FAA0F;AAC1F,4EAA4E;AAG5E,OAAO,EACL,cAAc,EACd,qBAAqB,EACrB,gBAAgB,EAChB,yBAAyB,GAC1B,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,2BAA2B,EAC3B,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,gCAAgC,EAChC,8BAA8B,EAC9B,yBAAyB,EACzB,wBAAwB,EACxB,uBAAuB,EACvB,wBAAwB,EACxB,4BAA4B,GAC7B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,uBAAuB,EACvB,4BAA4B,EAC5B,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,mBAAmB,EACnB,8BAA8B,EAC9B,0BAA0B,EAC1B,8BAA8B,EAC9B,8BAA8B,EAC9B,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,cAAc,EACd,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,sBAAsB,EACtB,6BAA6B,EAC7B,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,2BAA2B,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC/J,OAAO,EACL,sBAAsB,EACtB,+BAA+B,EAC/B,iCAAiC,GAClC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EACL,qBAAqB,EACrB,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,+BAA+B,EAC/B,uBAAuB,EACvB,4BAA4B,EAC5B,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,4BAA4B,EAC5B,iCAAiC,EACjC,2CAA2C,GAC5C,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,0BAA0B,EAC1B,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAC1B,kDAAkD;AAClD,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,EAC9B,mBAAmB,EACnB,4BAA4B,EAC5B,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,mEAAmE;AACnE,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,+BAA+B,EAC/B,2BAA2B,EAC3B,+BAA+B,EAC/B,8BAA8B,EAC9B,qCAAqC,EACrC,kCAAkC,EAClC,sCAAsC,EACtC,oCAAoC,GACrC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,8BAA8B,GAC/B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,6BAA6B,EAC7B,8CAA8C,EAC9C,sCAAsC,GACvC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,6BAA6B,EAC7B,iCAAiC,GAClC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EACL,yBAAyB,EACzB,kCAAkC,EAClC,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,wBAAwB,EACxB,8BAA8B,GAC/B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EACL,wCAAwC,EACxC,yCAAyC,GAC1C,MAAM,+BAA+B,CAAC;AACvC,0DAA0D;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EACL,6BAA6B,EAC7B,kCAAkC,EAClC,4BAA4B,EAC5B,kCAAkC,EAClC,+BAA+B,EAC/B,0BAA0B,EAC1B,qCAAqC,GACtC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAChB,8BAA8B,EAC9B,2BAA2B,EAC3B,6BAA6B,EAC7B,uBAAuB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EACL,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,wBAAwB,EACxB,yCAAyC,GAC1C,MAAM,kBAAkB,CAAC;AAE1B,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,oBAAoB;IACpB,uBAAuB,EAAE,cAAc;IACvC,4CAA4C,EAAE,qBAAqB;IACnE,0DAA0D,EAAE,4BAA4B;IACxF,yDAAyD,EAAE,gBAAgB;IAC3E,kDAAkD,EAAE,sBAAsB;IAC1E,8CAA8C,EAAE,4BAA4B;IAC5E,4DAA4D,EAAE,4BAA4B;IAC1F,yEAAyE,EAAE,uBAAuB;IAClG,mBAAmB,EAAE,gBAAgB;IAErC,mCAAmC;IACnC,iCAAiC,EAAE,qBAAqB;IACxD,sDAAsD,EAAE,mBAAmB;IAC3E,4DAA4D,EAAE,yBAAyB;IACvF,oEAAoE,EAAE,oBAAoB;IAC1F,2FAA2F,EAAE,cAAc;IAC3G,2DAA2D,EAAE,cAAc;IAC3E,oFAAoF,EAAE,iBAAiB;IACvG,2DAA2D,EAAE,cAAc;IAC3E,gFAAgF,EAAE,mBAAmB;IACrG,sEAAsE,EAAE,oBAAoB;IAC5F,qGAAqG,EAAE,2BAA2B;IAClI,wEAAwE,EAAE,sBAAsB;IAChG,4FAA4F;IAC5F,oCAAoC,EAAE,uBAAuB;IAC7D,0BAA0B,EAAE,eAAe;IAC3C,0CAA0C,EAAE,6BAA6B;IAEzE,8BAA8B;IAC9B,oDAAoD,EAAE,uBAAuB;IAC7E,iCAAiC,EAAE,mBAAmB;IACtD,4BAA4B,EAAE,gBAAgB;IAC9C,kCAAkC,EAAE,mBAAmB;IACvD,8EAA8E;IAC9E,gCAAgC,EAAE,2BAA2B;IAE7D,uCAAuC;IACvC,kCAAkC,EAAE,mBAAmB;IACvD,6CAA6C,EAAE,8BAA8B;IAC7E,uCAAuC,EAAE,0BAA0B;IACnE,sCAAsC,EAAE,8BAA8B;IACtE,0CAA0C,EAAE,8BAA8B;IAC1E,6BAA6B,EAAE,4BAA4B;IAC3D,kCAAkC,EAAE,yBAAyB;IAE7D,+BAA+B;IAC/B,kCAAkC,EAAE,mBAAmB;IACvD,wBAAwB,EAAE,uBAAuB;IACjD,qFAAqF;IACrF,sFAAsF;IACtF,uEAAuE;IACvE,uCAAuC,EAAE,sBAAsB;IAC/D,uCAAuC,EAAE,wBAAwB;IACjE,4CAA4C,EAAE,gCAAgC;IAC9E,6CAA6C,EAAE,8BAA8B;IAE7E,oCAAoC;IACpC,0CAA0C,EAAE,2BAA2B;IACvE,qFAAqF,EAAE,wBAAwB;IAC/G,4BAA4B,EAAE,cAAc;IAC5C,8DAA8D,EAAE,mBAAmB;IAEnF,2CAA2C;IAC3C,qFAAqF;IACrF,iFAAiF;IACjF,4DAA4D;IAC5D,2BAA2B,EAAE,2BAA2B;IACxD,uDAAuD,EAAE,8BAA8B;IACvF,4CAA4C,EAAE,4BAA4B;IAC1E,6CAA6C,EAAE,uBAAuB;IACtE,+BAA+B,EAAE,mBAAmB;IACpD,qBAAqB,EAAE,kBAAkB;IACzC,iCAAiC,EAAE,sBAAsB;IACzD,wCAAwC,EAAE,+BAA+B;IACzE,mEAAmE,EAAE,iCAAiC;IACtG,uBAAuB,EAAE,mBAAmB;IAC5C,iCAAiC,EAAE,0BAA0B;IAC7D,0CAA0C,EAAE,mBAAmB;IAC/D,wFAAwF,EAAE,mBAAmB;IAE7G,6BAA6B;IAC7B,+BAA+B,EAAE,kBAAkB;IACnD,sCAAsC,EAAE,0BAA0B;IAClE,4BAA4B,EAAE,gBAAgB;IAC9C,6BAA6B,EAAE,wBAAwB;IAEvD,4BAA4B;IAC5B,0CAA0C,EAAE,qBAAqB;IACjE,2CAA2C,EAAE,qBAAqB;IAClE,2CAA2C,EAAE,4BAA4B;IACzE,uCAAuC,EAAE,yBAAyB;IAElE,sEAAsE;IACtE,qCAAqC,EAAE,0BAA0B;IACjE,gCAAgC,EAAE,2BAA2B;IAE7D,yDAAyD;IACzD,0CAA0C,EAAE,+BAA+B;IAC3E,8BAA8B,EAAE,uBAAuB;IACvD,+CAA+C,EAAE,4BAA4B;IAC7E,0BAA0B,EAAE,mBAAmB;IAC/C,4BAA4B,EAAE,uBAAuB;IACrD,+BAA+B,EAAE,uBAAuB;IACxD,qCAAqC,EAAE,4BAA4B;IACnE,sCAAsC,EAAE,iCAAiC;IACzE,oEAAoE,EAAE,2CAA2C;IAEjH,iCAAiC;IACjC,wDAAwD,EAAE,yBAAyB;IAEnF,oCAAoC;IACpC,6CAA6C,EAAE,yBAAyB;IACxE,4CAA4C,EAAE,uBAAuB;IACrE,+BAA+B,EAAE,8BAA8B;IAC/D,sBAAsB,EAAE,eAAe;IACvC,2BAA2B,EAAE,mBAAmB;IAChD,mEAAmE,EAAE,oBAAoB;IACzF,4BAA4B,EAAE,+BAA+B;IAE7D,mEAAmE;IACnE,8BAA8B,EAAE,2BAA2B;IAC3D,iCAAiC,EAAE,uBAAuB;IAC1D,2BAA2B,EAAE,uBAAuB;IACpD,oDAAoD,EAAE,+BAA+B;IACrF,kDAAkD,EAAE,2BAA2B;IAC/E,iEAAiE,EAAE,+BAA+B;IAClG,0CAA0C,EAAE,8BAA8B;IAC1E,8DAA8D,EAAE,qCAAqC;IACrG,2DAA2D,EAAE,kCAAkC;IAC/F,0EAA0E,EAAE,sCAAsC;IAClH,kDAAkD,EAAE,oCAAoC;IACxF,oCAAoC,EAAE,8BAA8B;IAEpE,+DAA+D;IAC/D,4BAA4B,EAAE,qBAAqB;IACnD,uCAAuC,EAAE,0BAA0B;IACnE,uCAAuC,EAAE,6BAA6B;IACtE,sEAAsE,EAAE,8CAA8C;IACtH,0DAA0D,EAAE,sCAAsC;IAElG,gEAAgE;IAChE,gFAAgF;IAChF,mFAAmF;IACnF,4DAA4D;IAC5D,sCAAsC,EAAE,8BAA8B;IACtE,4BAA4B,EAAE,yBAAyB;IACvD,2CAA2C,EAAE,6BAA6B;IAC1E,qDAAqD,EAAE,iCAAiC;IACxF,2BAA2B,EAAE,uBAAuB;IAEpD,qDAAqD;IACrD,6BAA6B,EAAE,yBAAyB;IACxD,qDAAqD,EAAE,kCAAkC;IACzF,kCAAkC,EAAE,0BAA0B;IAC9D,gDAAgD,EAAE,4BAA4B;IAE9E,8DAA8D;IAC9D,+BAA+B,EAAE,wBAAwB;IACzD,+BAA+B,EAAE,8BAA8B;IAE/D,4DAA4D;IAC5D,kCAAkC,EAAE,2BAA2B;IAE/D,+FAA+F;IAC/F,gGAAgG;IAChG,yCAAyC,EAAE,wCAAwC;IACnF,0CAA0C,EAAE,yCAAyC;IAErF,0DAA0D;IAC1D,gCAAgC,EAAE,sBAAsB;IACxD,gCAAgC,EAAE,6BAA6B;IAC/D,kDAAkD,EAAE,kCAAkC;IACtF,2DAA2D,EAAE,4BAA4B;IACzF,+DAA+D,EAAE,kCAAkC;IACnG,mDAAmD,EAAE,+BAA+B;IACpF,sDAAsD,EAAE,0BAA0B;IAClF,oBAAoB,EAAE,gBAAgB;IACtC,mDAAmD,EAAE,8BAA8B;IACnF,6CAA6C,EAAE,2BAA2B;IAC1E,8CAA8C,EAAE,6BAA6B;IAC7E,2CAA2C,EAAE,uBAAuB;IACpE,6CAA6C,EAAE,qCAAqC;IACpF,sFAAsF;IACtF,4EAA4E;IAC5E,uCAAuC,EAAE,qCAAqC;IAC9E,6BAA6B,EAAE,yBAAyB;IACxD,yBAAyB,EAAE,sBAAsB;IACjD,iDAAiD,EAAE,yBAAyB;IAE5E,0CAA0C;IAC1C,aAAa,EAAE,eAAe;IAC9B,qBAAqB,EAAE,yBAAyB;IAChD,4BAA4B,EAAE,wBAAwB;IACtD,4EAA4E;IAC5E,4EAA4E;IAC5E,+EAA+E;IAC/E,wBAAwB,EAAE,uBAAuB;IACjD,uBAAuB,EAAE,uBAAuB;IAChD,4BAA4B,EAAE,wBAAwB;IAEtD,+FAA+F;IAC/F,uBAAuB,EAAE,uBAAuB;IAChD,wBAAwB,EAAE,wBAAwB;IAClD,wCAAwC,EAAE,yCAAyC;IAEnF,qCAAqC;IACrC,uBAAuB,EAAE,eAAe;IACxC,2BAA2B,EAAE,mBAAmB;IAChD,+BAA+B,EAAE,uBAAuB;IACxD,mCAAmC,EAAE,2BAA2B;IAChE,qBAAqB,EAAE,mBAAmB;CACK,CAAC;AAIlD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,2DAA2D,EAAE,KAAK;IAClE,oFAAoF,EAAE,KAAK;IAC3F,2DAA2D,EAAE,KAAK;IAClE,gFAAgF,EAAE,KAAK;IACvF,sEAAsE,EAAE,KAAK;IAC7E,qGAAqG,EAAE,KAAK;IAC5G,wEAAwE,EAAE,oBAAoB;IAC9F,uFAAuF;IACvF,oFAAoF;IACpF,uCAAuC,EAAE,KAAK;IAC9C,uCAAuC,EAAE,KAAK;IAC9C,4CAA4C,EAAE,KAAK;IACnD,0CAA0C,EAAE,IAAI;IAChD,2CAA2C,EAAE,IAAI;IACjD,2CAA2C,EAAE,qBAAqB;IAClE,4DAA4D,EAAE,qBAAqB;IACnF,uCAAuC,EAAE,IAAI;IAC7C,4BAA4B,EAAE,KAAK;CACiC,CAAC;AAEvE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAsB;IACpD,cAAc;IACd,iBAAiB;IACjB,kBAAkB;IAClB,oFAAoF;IACpF,oEAAoE;IACpE,eAAe;CACP,CAAC","sourcesContent":["// Firestore collection registry — the single, authoritative binding from each Firestore\n// collection/subcollection path template to its document Zod schema. This is the input to\n// the schema-doc generator and the drift-check, and its completeness is CI-enforced\n// (registry.test.ts) against the COLLECTIONS / *_SUBCOLLECTIONS name constants, so a new\n// collection cannot be added without either a schema or an explicit PENDING entry.\n//\n// Path templates reuse the segment names from ../paths/collections.ts (and the shapes the\n// path-builders produce). `{placeholder}` segments are document/parent IDs.\n\nimport type { z } from 'zod';\nimport {\n FullUserSchema,\n UserPrivateDataSchema,\n CraftSkillSchema,\n CraftSkillReferenceSchema,\n} from './user.js';\nimport { PublicUserSchema } from './publicUser.js';\nimport { AccountDeletionRequestV1Schema } from './account-deletion.js';\nimport {\n FullWorkProjectSchema,\n PublicWorkProjectSchema,\n WorkFileFolderSchema,\n WorkFileSchema,\n WorkRealmSchema,\n GuildmateUserSchema,\n PublicGuildmateUserSchema,\n} from './work-project.js';\nimport {\n FullTaleSchema,\n FullChapterSchema,\n FullTuneSchema,\n FullTuneTrackSchema,\n FullTelevisionSchema,\n FullTelevisionEpisodeSchema,\n ThresholdItemSchema,\n PublishedHallItemSchema,\n PublishedChapterSchema,\n PublishedTuneTrackSchema,\n PublishedTelevisionEpisodeSchema,\n HallContentChangeRequestSchema,\n FuturePlansDocumentSchema,\n RulesAndAgreementsSchema,\n LegalPageDocumentSchema,\n TakeItDownPageCopySchema,\n HallLibraryPreferencesSchema,\n} from './content.js';\nimport {\n SquareStreetzPostSchema,\n MentionHistoryDocumentSchema,\n FollowEdgeSchema,\n FollowCounterSchema,\n SquareStreetzLikeSchema,\n TrendingPostsSchema,\n} from './social.js';\nimport {\n PledgePaymentSchema,\n PledgePaymentProviderRefSchema,\n ProcessedStripeEventSchema,\n PledgePaymentLedgerEventSchema,\n PaymentWebhookQuarantineSchema,\n PledgePaymentTotalsDocSchema,\n PledgeRefundRequestSchema,\n} from './payments.js';\nimport {\n FullCommissionListingSchema,\n CommissionProposalSchema,\n AuditionSchema,\n AuditionEntrySchema,\n UserAuditionVoteSchema,\n} from './commissions.js';\nimport {\n GuildChatChannelSchema,\n GuildInviteConversationSchema,\n AdminDispatchSchema,\n ChatMessageV1Schema,\n} from './messaging.js';\nimport { AppConfigSchema, AdminListSchema, ProfanityListSchema, ReservedUsernamesSchema, BlockedFranchiseNamesSchema, AppModeMarkerSchema } from './system.js';\nimport {\n ContentViolationSchema,\n ModerationCascadeManifestSchema,\n ModerationCascadeChangedDocSchema,\n} from './moderation.js';\nimport {\n AdminTaskDocSchema,\n} from './report-docs.js';\nimport { TTTAuditEventSchema } from './audit.js';\nimport {\n NotificationDocSchema,\n NotificationHistoryDocSchema,\n PendingNotificationSchema,\n} from './notifications.js';\nimport {\n NotificationDeliverySchema,\n NotificationFanoutJobSchema,\n} from './notification-ledger.js';\nimport {\n ChatChannelAuthProjectionSchema,\n ChatScopeDegradedSchema,\n ChatScopeDegradedCauseSchema,\n ChatSyncEventSchema,\n ChatSyncFanoutJobSchema,\n ChatMessageOutboxSchema,\n ChatAdminActionCommandSchema,\n ChatHistoryAnonymizationJobSchema,\n ChatHistoryAnonymizationAffectedChunkSchema,\n} from './chat-sync.js';\nimport { SquareAnnouncementJobSchema } from './square-announcement-jobs.js';\nimport { PendingMediaSchema, ArchivedPendingMediaSchema } from '../media/pending-media.js';\nimport { MediaAssetSchema } from './media-assets.js';\nimport { MediaActivationJobSchema } from './media-activation-jobs.js';\nimport {\n ReservedDisplayNameSchema,\n ReservedRealmNameSchema,\n StakeShareAuditEventSchema,\n ShortLinkSchema,\n FeedbackAliasSchema,\n UserSuggestionSchema,\n StatusReconcileQueueEntrySchema,\n} from './operational.js';\n// ===== Trust & Safety — report spine (§A1) =====\nimport {\n ProtectedReportRootV1Schema,\n ReportPublicProjectionV1Schema,\n ReportGroupV1Schema,\n ReportTargetSnapshotV1Schema,\n NarrativeRecordV1Schema,\n} from './safety/report.js';\nimport { SafetyCaseAlertV1Schema } from './safety/case-alert.js';\n// ===== Trust & Safety — child-safety case spine (§A1b, §A2) =====\nimport {\n ChildSafetyCaseListV1Schema,\n ChildSafetyCaseV1Schema,\n ChildSafetySourceSignalV1Schema,\n ChildSafetyDecisionV1Schema,\n ChildSafetyDecisionViewV1Schema,\n ChildSafetyCaseAccountV1Schema,\n ChildSafetyCaseAccountHistoryV1Schema,\n ChildSafetyNcmecSubmissionV1Schema,\n ChildSafetyNcmecSubmissionFileV1Schema,\n ChildSafetyLegalProcessEventV1Schema,\n} from './safety/case.js';\nimport {\n ChildSafetyOwningAliasV1Schema,\n} from './safety/case-aliases.js';\nimport {\n SafetyHoldRefV1Schema,\n SafetyHoldResourceV1Schema,\n SafetyResourceCommandV1Schema,\n SafetyResourceCommandAuthorizedRequestV1Schema,\n SafetyResourceCommandBypassRefV1Schema,\n} from './safety/holds.js';\nimport {\n SafetyEvidenceManifestV1Schema,\n SafetyEvidenceJobV1Schema,\n SafetyEvidenceJobItemV1Schema,\n SafetyEvidenceDispositionV1Schema,\n} from './safety/evidence.js';\nimport { EventProvenanceV1Schema } from './safety/provenance.js';\nimport {\n QuarantineSagaJobV1Schema,\n QuarantineSagaRelatedAssetV1Schema,\n NcmecSubmissionJobV1Schema,\n AccountActionCommandV1Schema,\n} from './safety/sagas.js';\nimport {\n SafetySlaMonitorV1Schema,\n SafetyMonitorHeartbeatV1Schema,\n} from './safety/monitors.js';\nimport { AgeAttestationNonceV1Schema, AgePolicyConfigV1Schema } from './safety/age.js';\nimport {\n PrivilegedReviewerPasskeyProfileV1Schema,\n PrivilegedReviewerCapabilityGrantV1Schema,\n} from './safety/reviewer-security.js';\n// ===== Trust & Safety — NCII / TAKE IT DOWN (§A11) =====\nimport { NciiAllegationV1Schema } from './ncii/allegations.js';\nimport {\n TakeItDownRequestRootV1Schema,\n TakeItDownRequesterPrivateV1Schema,\n TakeItDownSubmissionV1Schema,\n TakeItDownValidityDecisionV1Schema,\n TakeItDownRequestActionV1Schema,\n TakeItDownEvidenceV1Schema,\n NciiRetainedEvidenceInventoryV1Schema,\n} from './ncii/requests.js';\nimport {\n NciiCaseV1Schema,\n NciiCaseAllegationLinkV1Schema,\n NciiCaseRequestLinkV1Schema,\n NciiCaseRemovalActionV1Schema,\n NciiBlockedHashV1Schema,\n} from './ncii/cases.js';\nimport { NciiTemporaryHoldV1Schema } from './ncii/holds.js';\nimport {\n NciiRemovalJobV1Schema,\n NciiRemovalTargetV1Schema,\n} from './ncii/removal.js';\nimport {\n NciiPolicyConfigV1Schema,\n PrivilegedReviewerSecurityProfileV1Schema,\n} from './ncii/config.js';\n\nexport const COLLECTION_SCHEMAS = {\n // ===== Users =====\n 'userProfiles/{userId}': FullUserSchema,\n 'userProfiles/{userId}/privateData/{userId}': UserPrivateDataSchema,\n 'userProfiles/{userId}/privateData/hallLibraryPreferences': HallLibraryPreferencesSchema,\n 'userProfiles/{userId}/profileCraftSkills/{craftSkillId}': CraftSkillSchema,\n 'userProfiles/{userId}/auditionVotes/{auditionId}': UserAuditionVoteSchema,\n 'userProfiles/{userId}/mentionHistory/{docId}': MentionHistoryDocumentSchema,\n 'userProfiles/{userId}/notificationHistory/{notificationId}': NotificationHistoryDocSchema,\n 'userProfiles/{userId}/userLikes/likeHistory/squareStreetzLikes/{postId}': SquareStreetzLikeSchema,\n 'publicUsers/{uid}': PublicUserSchema,\n\n // ===== Work / Realm / Guild =====\n 'allWorkProjects/{workProjectId}': FullWorkProjectSchema,\n 'allWorkProjects/{workProjectId}/guildmateUsers/{uid}': GuildmateUserSchema,\n 'allWorkProjects/{workProjectId}/publicGuildmateUsers/{uid}': PublicGuildmateUserSchema,\n 'allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}': WorkFileFolderSchema,\n 'allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}/workFiles/{workFileId}': WorkFileSchema,\n 'allWorkProjects/{workProjectId}/workProjectTales/{taleId}': FullTaleSchema,\n 'allWorkProjects/{workProjectId}/workProjectTales/{taleId}/taleChapters/{chapterId}': FullChapterSchema,\n 'allWorkProjects/{workProjectId}/workProjectTunes/{tuneId}': FullTuneSchema,\n 'allWorkProjects/{workProjectId}/workProjectTunes/{tuneId}/tuneTracks/{trackId}': FullTuneTrackSchema,\n 'allWorkProjects/{workProjectId}/workProjectTelevision/{televisionId}': FullTelevisionSchema,\n 'allWorkProjects/{workProjectId}/workProjectTelevision/{televisionId}/televisionEpisodes/{episodeId}': FullTelevisionEpisodeSchema,\n 'allWorkProjects/{workProjectId}/guildChatChannels/{guildChatChannelId}': GuildChatChannelSchema,\n // Guild channel + invite messages are REALTIME-ONLY (chat Worker DO) — no Firestore schema.\n 'publicWorkProjects/{workProjectId}': PublicWorkProjectSchema,\n 'workRealms/{workRealmId}': WorkRealmSchema,\n 'guildInviteConversations/{guildInviteId}': GuildInviteConversationSchema,\n\n // ===== Square / Social =====\n 'squareStreetzFeed/activePosts/socialPosts/{postId}': SquareStreetzPostSchema,\n 'squareStreetzFeed/trendingPosts': TrendingPostsSchema,\n 'followEdges/{followEdgeId}': FollowEdgeSchema,\n 'followCounters/{followCounterId}': FollowCounterSchema,\n // Durable Square announcement outbox (Admin-SDK-only; deterministic job ids).\n 'squareAnnouncementJobs/{jobId}': SquareAnnouncementJobSchema,\n\n // ===== Payments / pledge ledger =====\n 'pledgePayments/{pledgePaymentId}': PledgePaymentSchema,\n 'pledgePaymentProviderRefs/{pledgePaymentId}': PledgePaymentProviderRefSchema,\n 'processedStripeEvents/{stripeEventId}': ProcessedStripeEventSchema,\n 'pledgePaymentLedgerEvents/{ledgerId}': PledgePaymentLedgerEventSchema,\n 'paymentWebhookQuarantine/{stripeEventId}': PaymentWebhookQuarantineSchema,\n 'pledgePaymentTotals/summary': PledgePaymentTotalsDocSchema,\n 'pledgeRefundRequests/{requestId}': PledgeRefundRequestSchema,\n\n // ===== Threshold / Hall =====\n 'thresholdItems/{thresholdItemId}': ThresholdItemSchema,\n 'hallItems/{hallItemId}': PublishedHallItemSchema,\n // Published hall sub-item projections — the chapter/track/episode docs copied out of\n // the Work at publish time (runPublishApprovedHallLibraryItem). Segment names are the\n // HALL_ITEM_SUBCOLLECTIONS constants (the lowercased WorkProjectType).\n 'hallItems/{hallItemId}/tales/{itemId}': PublishedChapterSchema,\n 'hallItems/{hallItemId}/tunes/{itemId}': PublishedTuneTrackSchema,\n 'hallItems/{hallItemId}/television/{itemId}': PublishedTelevisionEpisodeSchema,\n 'hallContentChangeRequests/{changeRequestId}': HallContentChangeRequestSchema,\n\n // ===== Commission / Audition =====\n 'commissionListings/{commissionListingId}': FullCommissionListingSchema,\n 'commissionListings/{commissionListingId}/commissionProposals/{commissionProposalId}': CommissionProposalSchema,\n 'auditionBoard/{auditionId}': AuditionSchema,\n 'auditionBoard/{auditionId}/auditionEntries/{auditionEntryId}': AuditionEntrySchema,\n\n // ===== Moderation / Reports / Admin =====\n // The report spine (§A1): the restricted root, its public projection subdoc, and the\n // dedup/count group. The root + projection are written by the app's submitReport\n // callable; the group is maintained by an app-side trigger.\n 'contentReports/{reportId}': ProtectedReportRootV1Schema,\n 'contentReports/{reportId}/publicProjection/{reportId}': ReportPublicProjectionV1Schema,\n 'contentReports/{reportId}/private/snapshot': ReportTargetSnapshotV1Schema,\n 'contentReports/{reportId}/private/narrative': NarrativeRecordV1Schema,\n 'activeReportGroups/{groupKey}': ReportGroupV1Schema,\n 'adminTasks/{taskId}': AdminTaskDocSchema,\n 'contentViolations/{violationId}': ContentViolationSchema,\n 'moderationCascadeManifests/{cascadeId}': ModerationCascadeManifestSchema,\n 'moderationCascadeManifests/{cascadeId}/changedDocs/{changedDocId}': ModerationCascadeChangedDocSchema,\n 'auditEvents/{eventId}': TTTAuditEventSchema,\n 'stakeShareAuditEvents/{eventId}': StakeShareAuditEventSchema,\n 'pendingAdminDispatches/{adminDispatchId}': AdminDispatchSchema,\n 'pendingAdminDispatches/{adminDispatchId}/conversationMessages/{adminDispatchMessageId}': ChatMessageV1Schema,\n\n // ===== Media pipeline =====\n 'pendingMedia/{pendingMediaId}': PendingMediaSchema,\n 'pendingMediaArchive/{pendingMediaId}': ArchivedPendingMediaSchema,\n 'mediaAssets/{mediaAssetId}': MediaAssetSchema,\n 'mediaActivationJobs/{jobId}': MediaActivationJobSchema,\n\n // ===== Notifications =====\n 'activeUserNotifications/{notificationId}': NotificationDocSchema,\n 'activeAdminNotifications/{notificationId}': NotificationDocSchema,\n 'adminNotificationHistory/{notificationId}': NotificationHistoryDocSchema,\n 'pendingNotifications/{notificationId}': PendingNotificationSchema,\n\n // ===== Notification redesign — delivery ledger + fanout engine =====\n 'notificationDeliveries/{deliveryId}': NotificationDeliverySchema,\n 'notificationFanoutJobs/{jobId}': NotificationFanoutJobSchema,\n\n // ===== Chat realtime sync / projection / commands =====\n 'chatChannelAuthProjections/{authPairKey}': ChatChannelAuthProjectionSchema,\n 'chatScopeDegraded/{scopeKey}': ChatScopeDegradedSchema,\n 'chatScopeDegraded/{scopeKey}/causes/{causeId}': ChatScopeDegradedCauseSchema,\n 'chatSyncEvents/{eventId}': ChatSyncEventSchema,\n 'chatSyncFanoutJobs/{jobId}': ChatSyncFanoutJobSchema,\n 'chatMessageOutbox/{commandId}': ChatMessageOutboxSchema,\n 'chatAdminActionCommands/{requestId}': ChatAdminActionCommandSchema,\n 'chatHistoryAnonymizationJobs/{jobId}': ChatHistoryAnonymizationJobSchema,\n 'chatHistoryAnonymizationJobs/{jobId}/affectedChunks/{chunkOrdinal}': ChatHistoryAnonymizationAffectedChunkSchema,\n\n // ===== Craft skills index =====\n 'craftSkillsByTag/{tag}/taggedCraftSkills/{compositeId}': CraftSkillReferenceSchema,\n\n // ===== Operational / utility =====\n 'reservedDisplayNames/{displayNameUppercase}': ReservedDisplayNameSchema,\n 'reservedRealmNames/{workingTitleUppercase}': ReservedRealmNameSchema,\n 'accountDeletionRequests/{uid}': AccountDeletionRequestV1Schema,\n 'shortLinks/{shortId}': ShortLinkSchema,\n 'feedbackAliases/{aliasId}': FeedbackAliasSchema,\n 'feedbackSubmissions/{feedbackType}/userSuggestions/{suggestionId}': UserSuggestionSchema,\n 'statusReconcileQueue/{uid}': StatusReconcileQueueEntrySchema,\n\n // ===== Trust & Safety — child-safety case spine (§A1b, §A2) =====\n 'childSafetyCaseList/{caseId}': ChildSafetyCaseListV1Schema,\n 'activeSafetyCaseAlerts/{caseId}': SafetyCaseAlertV1Schema,\n 'childSafetyCases/{caseId}': ChildSafetyCaseV1Schema,\n 'childSafetyCases/{caseId}/sourceSignals/{signalId}': ChildSafetySourceSignalV1Schema,\n 'childSafetyCases/{caseId}/decisions/{decisionId}': ChildSafetyDecisionV1Schema,\n 'childSafetyCases/{caseId}/decisions/{decisionId}/views/{viewId}': ChildSafetyDecisionViewV1Schema,\n 'childSafetyCases/{caseId}/accounts/{uid}': ChildSafetyCaseAccountV1Schema,\n 'childSafetyCases/{caseId}/accounts/{uid}/history/{historyId}': ChildSafetyCaseAccountHistoryV1Schema,\n 'childSafetyCases/{caseId}/ncmecSubmissions/{submissionId}': ChildSafetyNcmecSubmissionV1Schema,\n 'childSafetyCases/{caseId}/ncmecSubmissions/{submissionId}/files/{fileId}': ChildSafetyNcmecSubmissionFileV1Schema,\n 'childSafetyCases/{caseId}/legalProcess/{eventId}': ChildSafetyLegalProcessEventV1Schema,\n 'childSafetyOwningAliases/{aliasId}': ChildSafetyOwningAliasV1Schema,\n\n // ===== Trust & Safety — holds + resource commands (§A3) =====\n 'safetyHoldRefs/{holdRefId}': SafetyHoldRefV1Schema,\n 'safetyHoldResources/{resourceKeyHash}': SafetyHoldResourceV1Schema,\n 'safetyResourceCommands/{commandDocId}': SafetyResourceCommandV1Schema,\n 'safetyResourceCommands/{commandDocId}/authorizedRequests/{requestId}': SafetyResourceCommandAuthorizedRequestV1Schema,\n 'safetyResourceCommands/{commandDocId}/bypassRefs/{refId}': SafetyResourceCommandBypassRefV1Schema,\n\n // ===== Trust & Safety — evidence + provenance (§A4, §A6) =====\n // SafetyEvidenceManifestV1Schema is a refined ZodObject (superRefine for the H5\n // sourceKind invariant); the schema-doc generator unwraps the effect to introspect\n // its shape, so binding the refined schema here is correct.\n 'safetyEvidenceManifests/{manifestId}': SafetyEvidenceManifestV1Schema,\n 'safetyEvidenceJobs/{jobId}': SafetyEvidenceJobV1Schema,\n 'safetyEvidenceJobs/{jobId}/items/{itemId}': SafetyEvidenceJobItemV1Schema,\n 'safetyEvidenceJobs/{jobId}/disposition/{locationId}': SafetyEvidenceDispositionV1Schema,\n 'eventProvenance/{eventId}': EventProvenanceV1Schema,\n\n // ===== Trust & Safety — sagas + closure (§A5) =====\n 'quarantineSagaJobs/{caseId}': QuarantineSagaJobV1Schema,\n 'quarantineSagaJobs/{caseId}/relatedAssets/{assetId}': QuarantineSagaRelatedAssetV1Schema,\n 'ncmecSubmissionJobs/{ncmecJobId}': NcmecSubmissionJobV1Schema,\n 'accountActionCommands/{accountActionCommandId}': AccountActionCommandV1Schema,\n\n // ===== Trust & Safety — SLA monitors + heartbeat (§A8) =====\n 'safetySlaMonitors/{monitorId}': SafetySlaMonitorV1Schema,\n 'safetyMonitorHeartbeat/global': SafetyMonitorHeartbeatV1Schema,\n\n // ===== Trust & Safety — age attestation nonces (§A7) =====\n 'ageAttestationNonces/{nonceHash}': AgeAttestationNonceV1Schema,\n\n // ===== Trust & Safety — per-operator privileged-reviewer security (§A11 [M-6] / [H-17]) =====\n // Backend-only (Cloud-Functions-only readers/writers; client access denied in firestore.rules).\n 'privilegedReviewerPasskeyProfiles/{uid}': PrivilegedReviewerPasskeyProfileV1Schema,\n 'privilegedReviewerCapabilityGrants/{uid}': PrivilegedReviewerCapabilityGrantV1Schema,\n\n // ===== Trust & Safety — NCII / TAKE IT DOWN (§A11) =====\n 'nciiAllegations/{allegationId}': NciiAllegationV1Schema,\n 'takeItDownRequests/{requestId}': TakeItDownRequestRootV1Schema,\n 'takeItDownRequests/{requestId}/private/requester': TakeItDownRequesterPrivateV1Schema,\n 'takeItDownRequests/{requestId}/submissions/{submissionId}': TakeItDownSubmissionV1Schema,\n 'takeItDownRequests/{requestId}/validityDecisions/{decisionId}': TakeItDownValidityDecisionV1Schema,\n 'takeItDownRequests/{requestId}/actions/{actionId}': TakeItDownRequestActionV1Schema,\n 'takeItDownRequests/{requestId}/evidence/{evidenceId}': TakeItDownEvidenceV1Schema,\n 'nciiCases/{caseId}': NciiCaseV1Schema,\n 'nciiCases/{caseId}/allegationLinks/{allegationId}': NciiCaseAllegationLinkV1Schema,\n 'nciiCases/{caseId}/requestLinks/{requestId}': NciiCaseRequestLinkV1Schema,\n 'nciiCases/{caseId}/removalActions/{actionId}': NciiCaseRemovalActionV1Schema,\n 'nciiCases/{caseId}/blockedHashes/{hashId}': NciiBlockedHashV1Schema,\n 'nciiRetainedEvidenceInventory/{inventoryId}': NciiRetainedEvidenceInventoryV1Schema,\n // [H-01] dead-letter sink for inventory rows that could not be written to the primary\n // nciiRetainedEvidenceInventory collection. Stores the same document shape.\n 'nciiInventoryDeadLetter/{inventoryId}': NciiRetainedEvidenceInventoryV1Schema,\n 'nciiTemporaryHolds/{holdId}': NciiTemporaryHoldV1Schema,\n 'nciiRemovalJobs/{jobId}': NciiRemovalJobV1Schema,\n 'nciiRemovalJobs/{jobId}/targets/{targetKeyHash}': NciiRemovalTargetV1Schema,\n\n // ===== _config singletons (public) =====\n '_config/app': AppConfigSchema,\n '_config/futurePlans': FuturePlansDocumentSchema,\n '_config/rulesAndAgreements': RulesAndAgreementsSchema,\n // Content-pages migration (DJ ruling 2026-07-06): /terms, /privacy, and the\n // /take-it-down page copy render exclusively from these (all public pages —\n // take-it-down is a NO-LOGIN page, so its copy doc must be publicly readable).\n '_config/termsOfService': LegalPageDocumentSchema,\n '_config/privacyPolicy': LegalPageDocumentSchema,\n '_config/takeItDownPageCopy': TakeItDownPageCopySchema,\n\n // ===== _serverData singletons (server-only — Cloud-Functions-only readers, BACKEND-108) =====\n '_serverData/agePolicy': AgePolicyConfigV1Schema,\n '_serverData/nciiPolicy': NciiPolicyConfigV1Schema,\n '_serverData/privilegedReviewerSecurity': PrivilegedReviewerSecurityProfileV1Schema,\n\n // ===== _systemData singletons =====\n '_systemData/adminList': AdminListSchema,\n '_systemData/profanityList': ProfanityListSchema,\n '_systemData/reservedUsernames': ReservedUsernamesSchema,\n '_systemData/blockedFranchiseNames': BlockedFranchiseNamesSchema,\n '_systemData/appMode': AppModeMarkerSchema,\n} as const satisfies Record<string, z.ZodTypeAny>;\n\nexport type RegisteredCollectionPath = keyof typeof COLLECTION_SCHEMAS;\n\n/**\n * Doc-id field annotation: for the listed bindings, the named body field equals the\n * Firestore document id and is injected at READ time (`{ ...doc.data(), <field>: doc.id }`),\n * never persisted — the write callables store the body via `Omit<…, '<field>'>`. The bound\n * schema models the (correct) consumer/read shape, where the field is required, so a raw\n * stored doc is \"missing\" it. The drift-check injects `{ [field]: doc.id, ...data }` before\n * validating, generalizing the one-off `AdminTaskDocSchema` stored-shape workaround into a\n * single mechanism so real-callable drift-checks don't false-flag every doc-id collection.\n * The schema-doc generator ignores this map. Keys are compiler-checked against the registry.\n */\nexport const COLLECTION_DOC_ID_FIELDS = {\n 'allWorkProjects/{workProjectId}/workProjectTales/{taleId}': 'uid',\n 'allWorkProjects/{workProjectId}/workProjectTales/{taleId}/taleChapters/{chapterId}': 'uid',\n 'allWorkProjects/{workProjectId}/workProjectTunes/{tuneId}': 'uid',\n 'allWorkProjects/{workProjectId}/workProjectTunes/{tuneId}/tuneTracks/{trackId}': 'uid',\n 'allWorkProjects/{workProjectId}/workProjectTelevision/{televisionId}': 'uid',\n 'allWorkProjects/{workProjectId}/workProjectTelevision/{televisionId}/televisionEpisodes/{episodeId}': 'uid',\n 'allWorkProjects/{workProjectId}/guildChatChannels/{guildChatChannelId}': 'guildChatChannelId',\n // Published hall sub-items: the doc id IS the live sub-item's id; `uid` is injected at\n // read (the publish writer spreads the live doc's stored body, which has no `uid`).\n 'hallItems/{hallItemId}/tales/{itemId}': 'uid',\n 'hallItems/{hallItemId}/tunes/{itemId}': 'uid',\n 'hallItems/{hallItemId}/television/{itemId}': 'uid',\n 'activeUserNotifications/{notificationId}': 'id',\n 'activeAdminNotifications/{notificationId}': 'id',\n 'adminNotificationHistory/{notificationId}': 'archiveOccurrenceId',\n 'userProfiles/{userId}/notificationHistory/{notificationId}': 'archiveOccurrenceId',\n 'pendingNotifications/{notificationId}': 'id',\n 'statusReconcileQueue/{uid}': 'uid',\n} as const satisfies Partial<Record<RegisteredCollectionPath, string>>;\n\n/**\n * Collections that exist (in COLLECTIONS / *_SUBCOLLECTIONS or firestore.rules) but are\n * intentionally NOT bound to a schema, each with a reason. Listed EXPLICITLY so completeness is\n * enforced and nothing is silently uncovered; the registry test fails if a NEW unlisted collection\n * appears. These three are the only remaining gaps after the schema-registry binding pass:\n *\n * - userMetadata: `userProfiles/{uid}/userMetadata/notificationSettings` — a firestore.rules\n * match and `PATH_BUILDERS.userMetadata` exist, but there is no live reader/writer and no\n * notification-settings type anywhere yet. Bind once that shape is implemented.\n * - checkedOutItems: a `userProfiles/{uid}/checkedOutItems` subcollection constant with no writer,\n * reader, rule, or path-builder (the admin \"checked out items\" UI reads adminTasks by\n * `checkoutDetails.userId`, not this subcollection). Vestigial — remove once confirmed safe.\n * - feedbackDenylist: `feedbackDenylist/{deniedWord}` — Console-managed (firestore.rules §3F: no\n * callable writes it) and submitFeedback reads it via `.exists` only, so there is no field\n * contract to author a schema from. The doc id is the denied word; the body is unused.\n */\nexport const PENDING_COLLECTIONS: readonly string[] = [\n 'userMetadata',\n 'checkedOutItems',\n 'feedbackDenylist',\n // Append-only NCII case closure/reopen event rows — the doc shape is owned app-side\n // (NciiCaseV1 closure events), not modeled in ttt-core doc-schemas.\n 'closureEvents',\n] as const;\n"]}
|
|
@@ -214,7 +214,7 @@ export const UserPrivateDataAgeFieldsSchema = z.object({
|
|
|
214
214
|
// artisans — the money boundary — so collection happens there, with UI copy warning the
|
|
215
215
|
// DOB must match the user's future payout identity. Server re-derives 18+ from the entered
|
|
216
216
|
// DOB; an under-18 derivation rejects with a failure audit and stores nothing. PII —
|
|
217
|
-
// privateData only (
|
|
217
|
+
// privateData only (BACKEND-105); same no-log posture as the raw DOB (scrubber + canary).
|
|
218
218
|
attestedDateOfBirth: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(), // 'YYYY-MM-DD'
|
|
219
219
|
attestedDobRecordedAt: z.number().optional(), // epoch ms
|
|
220
220
|
attestedDobSource: z.enum(['artisanOnboarding']).optional(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"age.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/age.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — age attestation, registration nonce, and account age-fields\n// (Appendix A §A7 — \"Age (full contract)\" + the §A11 [H6] concrete AgePolicyConfigV1\n// default block).\n//\n// This cluster owns:\n// - `ageAttestationNonces/{nonceHash}` (AgeAttestationNonceV1) — the one-time,\n// 256-bit server-generated registration nonce. Only the SHA-256 of the nonce is\n// the doc id; the raw nonce appears only inside the signed token.\n// - The pinned `ageBracketAttestation` JWS payload-claims shape [M-09] — the DECODED\n// claims of the compact JWS (JWT, RFC 7519, alg=HS256) issued at /api/age/attest\n// and verified at /api/register/complete.\n// - The `__Secure-ttt_age_session` cookie spec [F13] (an exported const, NOT a doc).\n// - `AgePolicyConfigV1` (the `_config/agePolicy` singleton) + its pinned literal\n// default const (§A11 [H6]).\n// - The teen→adult `ageUpgradeAttestation` token shape.\n// - `UserPrivateDataAgeFieldsSchema` — the STANDALONE age-fields shape that the\n// orchestrator merges into `UserPrivateDataSchema` (privateData/{uid}). This file\n// does NOT edit user.ts.\n//\n// Every field/enum/optionality/bound is transcribed verbatim from the frozen spec\n// (docs/code_changes_needed/trust-and-safety/IMPLEMENTATION_PLAN.md, Appendix A) — no\n// invented values, no placeholders.\n//\n// `RegistrationCompletionOutcome` is the DOMAIN outcome that feeds the orphan-Auth\n// deletion policy; it is the SINGLE SOURCE in ./foundation.js and is IMPORTED here\n// (never redefined).\n//\n// Timestamp convention: epoch-MILLISECONDS via z.number() — EXCEPT the JWS token\n// claims `iat`/`exp`, which are epoch-SECONDS per JWT (RFC 7519); those are commented\n// at the claim.\n\nimport { z } from 'zod';\nimport { RegistrationCompletionOutcomeSchema } from './foundation.js';\n\n// ===========================================================================\n// A7 — ageAttestationNonces/{nonceHash} (AgeAttestationNonceV1)\n// One-time, 256-bit server-generated nonce. Only the nonce's SHA-256 is the doc id;\n// the raw nonce appears only inside the signed token. 10-minute TTL; one successful\n// consume, transactionally bound to the new Auth uid AND the requestSessionHash;\n// expired/used/unknown fails closed. Spent records auto-delete ~24h after consume/expiry\n// via a Firestore native-TTL policy on `ttlExpireAt` (F-018) — no scheduled reaper.\n// ===========================================================================\n\n/** Server-derived audience bracket — NEVER client-derived. */\nexport const AgeBracketSchema = z.enum(['teen', 'adult']);\nexport type AgeBracket = z.infer<typeof AgeBracketSchema>;\n\n/** Nonce lifecycle status. `expired`/`consumed`/unknown all fail closed at consume. */\nexport const AgeAttestationNonceStatusSchema = z.enum(['issued', 'consumed', 'expired']);\nexport type AgeAttestationNonceStatus = z.infer<typeof AgeAttestationNonceStatusSchema>;\n\n/** `ageAttestationNonces/{nonceHash}` — the registration attestation nonce record.\n * Doc id is the SHA-256 hex of the 256-bit server nonce (deterministic; the raw\n * nonce lives only in the signed token, never in Firestore). */\nexport const AgeAttestationNonceV1Schema = z.object({\n schemaVersion: z.literal(1),\n bracket: AgeBracketSchema, // SERVER-derived audience bracket\n policyVersion: z.string().min(1), // the agePolicyVersion in force when issued\n signingKeyVersion: z.string().min(1), // the versioned KMS/Secret-Manager key that signs the token (= JWS `kid`)\n requestSessionHash: z.string().min(1), // SHA-256 of the registering session/request marker — the binding (High-6 §D)\n issuedAt: z.number(), // epoch ms\n expiresAt: z.number(), // epoch ms; issuedAt + 10-min TTL\n consumedAt: z.number().optional(), // epoch ms; set on the one successful consume\n consumedByUid: z.string().min(1).optional(), // the new Auth uid this nonce was transactionally bound to\n status: AgeAttestationNonceStatusSchema,\n // [Q21.5 REVISED — DJ 2026-07-06] The nonce carries NO date of birth for ANY bracket.\n // Registration never persists a DOB (adult or teen — only the derived bracket survives);\n // the previous adult-bracket `dateOfBirth` carry field was removed. The ONLY place a DOB\n // is ever persisted is becomeArtisanCreator ('artisanOnboarding') — see\n // UserPrivateDataAgeFieldsSchema below. Raw DOBs remain no-log everywhere.\n // [F-018] Firestore NATIVE-TTL field. Set to a real Firestore `Timestamp` of (consume/expire time +\n // ~24h) at the moment the nonce becomes spent; a TTL policy on `ageAttestationNonces.ttlExpireAt`\n // then auto-deletes the spent single-use record (no scheduled reaper). DOCUMENTED EXCEPTION to this\n // file's epoch-ms-number convention: native TTL requires a real Timestamp, and this field is\n // WRITE-ONLY (never read by app code), so it is typed opaquely here (`z.unknown`) to avoid pulling a\n // firebase `Timestamp` type into the environment-agnostic ttt-core schema layer (the app writes it via\n // `admin.firestore.Timestamp.fromMillis`, mirroring notification-core's `expireAt`). Absent until spent.\n ttlExpireAt: z.unknown().optional(),\n}).strict();\nexport type AgeAttestationNonceV1 = z.infer<typeof AgeAttestationNonceV1Schema>;\n\n// ===========================================================================\n// A7 [M-09] — ageBracketAttestation JWS payload claims (the ONE pinned wire format)\n//\n// The token is a COMPACT JWS (JWT, RFC 7519) with alg=HS256, signed by the versioned\n// KMS/Secret-Manager key. The schema below validates the DECODED PAYLOAD CLAIMS only.\n//\n// JOSE header (NOT part of this schema — documented for the verifier):\n// { \"alg\": \"HS256\", \"typ\": \"JWT\", \"kid\": <signingKeyVersion> } // kid = the exact signingKeyVersion\n//\n// Serialization: standard JWS compact form\n// base64url(header) '.' base64url(payload) '.' base64url(sig)\n// the signature is base64url (no padding); claim names + types are EXACTLY as below\n// (no extra claims).\n//\n// Verification REQUIRES (fail-closed on any miss): valid HS256 signature under the key\n// named by `kid`; aud == \"ttt-register-complete\"; iss == \"ttt-age-attest\"; exp not\n// passed; sub matches the ageAttestationNonces doc being consumed; rsh matches the\n// request's requestSessionHash.\n//\n// `iat`/`exp` are epoch-SECONDS (per JWT), NOT epoch-millis like the rest of this file.\n// ===========================================================================\n\nexport const AgeBracketAttestationClaimsV1Schema = z.object({\n iss: z.literal('ttt-age-attest'), // issuer\n aud: z.literal('ttt-register-complete'), // AUDIENCE/purpose binding — /api/register/complete MUST verify aud\n sub: z.string().min(1), // the SHA-256 nonce hash (also the ageAttestationNonces doc id)\n iat: z.number().int(), // epoch SECONDS (per JWT)\n exp: z.number().int(), // epoch SECONDS (per JWT); exp = iat + 600 (10-min TTL)\n bkt: AgeBracketSchema, // the SERVER-derived bracket (never client-derived)\n pv: z.string().min(1), // agePolicyVersion string\n rsh: z.string().min(1), // sha256(cookieValue) — the session binding\n}).strict();\nexport type AgeBracketAttestationClaimsV1 = z.infer<typeof AgeBracketAttestationClaimsV1Schema>;\n\n// ===========================================================================\n// A7 [F13] — Age-session cookie spec (`__Secure-ttt_age_session`)\n//\n// Pinned cookie attributes. The cookie VALUE is a cryptographically-random value\n// generated per registration attempt; only requestSessionHash = sha256(cookieValue)\n// is stored (with the nonce) — the raw cookie value is NEVER persisted. A separate\n// non-unique UX marker may exist for display, but is NEVER the security binding.\n//\n// `Domain` is omitted (host-only) — represented here by `hostOnly: true`.\n// ===========================================================================\n\nexport const AGE_SESSION_COOKIE_SPEC = {\n name: '__Secure-ttt_age_session',\n hostOnly: true, // Domain attribute omitted → host-only cookie\n path: '/api',\n secure: true,\n httpOnly: true,\n sameSite: 'Strict',\n maxAgeSeconds: 600, // 10 min\n} as const;\n\n// ===========================================================================\n// A7 / A11 [H6] — AgePolicyConfigV1 (the `_config/agePolicy` singleton)\n//\n// The generic gRPC retryable/terminal code lists are REMOVED — deletion is driven\n// ONLY by the RegistrationCompletionOutcome domain enum (§A7). No raw gRPC code ever\n// deletes an account. noDeleteOutcomes / terminalDeletableOutcomes are typed against\n// the imported RegistrationCompletionOutcome enum so the two arrays can never drift\n// from the domain outcome set.\n// ===========================================================================\n\nexport const AgePolicyConfigV1Schema = z.object({\n agePolicyVersion: z.string().min(1),\n registrationGracePeriodMinutes: z.number().int(),\n cleanupSchedule: z.string().min(1), // cron expression for the orphan-Auth cleanup worker\n ageTokenTtlSeconds: z.number().int(), // [M-09] token TTL\n keyRetirementVerificationMinutes: z.number().int(), // [M-09] retired-signingKeyVersion verification window (> TTL so no live token is orphaned by a rotation)\n noDeleteOutcomes: z.array(RegistrationCompletionOutcomeSchema),\n terminalDeletableOutcomes: z.array(RegistrationCompletionOutcomeSchema),\n}).strict();\nexport type AgePolicyConfigV1 = z.infer<typeof AgePolicyConfigV1Schema>;\n\n/** The pinned literal default for `_config/agePolicy` (§A11 [H6] concrete config\n * values). Build defaults — transcribed verbatim from the frozen spec. */\nexport const DEFAULT_AGE_POLICY_CONFIG_V1: AgePolicyConfigV1 = {\n agePolicyVersion: '2026-06-19.general-audience.v1',\n registrationGracePeriodMinutes: 30,\n cleanupSchedule: '*/15 * * * *',\n ageTokenTtlSeconds: 600,\n keyRetirementVerificationMinutes: 15,\n noDeleteOutcomes: [\n 'completed',\n 'alreadyCompletedSameUid',\n 'retryableInfrastructureFailure',\n 'reauthenticationRequired',\n 'appCheckRetryRequired',\n 'privateDataConflict',\n ],\n terminalDeletableOutcomes: [\n 'nonceExpired',\n 'nonceUnknown',\n 'nonceConsumedDifferentUid',\n 'sessionHashMismatch',\n 'attestationSignatureInvalid',\n 'policyVersionRejected',\n ],\n};\n\n// ===========================================================================\n// A7 — teen→adult ageUpgradeAttestation token\n//\n// A SEPARATE token (not the registration nonce) issued to an authenticated,\n// recently-reauthenticated session. Binds uid + accountCapabilityVersion +\n// policyVersion + issued/expiry + nonce; consumed ONLY for that uid+version; never\n// the registration nonce, never cross-account.\n//\n// This is a token claims shape (decoded payload), NOT a stored Firestore doc.\n// ===========================================================================\n\nexport const AgeUpgradeAttestationV1Schema = z.object({\n uid: z.string().min(1), // the authenticated, recently-reauthenticated account\n accountCapabilityVersion: z.number().int(), // the capability version this upgrade is bound to\n policyVersion: z.string().min(1), // agePolicyVersion in force\n issuedAt: z.number(), // epoch ms\n expiresAt: z.number(), // epoch ms\n nonce: z.string().min(1), // single-use upgrade nonce (never the registration nonce; never cross-account)\n}).strict();\nexport type AgeUpgradeAttestationV1 = z.infer<typeof AgeUpgradeAttestationV1Schema>;\n\n// ===========================================================================\n// A7 — UserPrivateData age fields (STANDALONE shape for the orchestrator)\n//\n// These fields live on `privateData/{uid}` (server-write-only). They are exported as\n// a STANDALONE object shape so the orchestrator can merge them into\n// `UserPrivateDataSchema` in user.ts WITHOUT this file editing user.ts.\n// ===========================================================================\n\n/** Manual age-correction audit stub (who corrected, when, why) — embedded on the\n * private user data when a reviewer hand-corrects the recorded age state. */\nexport const UserPrivateDataAgeManualCorrectionSchema = z.object({\n at: z.number(), // epoch ms\n actorId: z.string().min(1),\n reason: z.string().min(1),\n}).strict();\nexport type UserPrivateDataAgeManualCorrection = z.infer<typeof UserPrivateDataAgeManualCorrectionSchema>;\n\n/** STANDALONE age-fields shape — the orchestrator merges these into\n * `UserPrivateDataSchema` (privateData/{uid}, server-write-only). Exported as a raw\n * object shape (NOT a z.object) so it can be spread into the canonical schema. */\nexport const UserPrivateDataAgeFieldsSchema = z.object({\n accountType: AgeBracketSchema, // 'teen' | 'adult'\n is18Plus: z.boolean(),\n agePolicyVersion: z.string().min(1),\n accountCapabilityVersion: z.number().int(),\n ageAttestedAt: z.number(), // epoch ms\n adultUpgradedAt: z.number().optional(), // epoch ms; set on a successful teen→adult upgrade\n ageManualCorrection: UserPrivateDataAgeManualCorrectionSchema.optional(),\n // [Q21.5 REVISED — DJ 2026-07-06, counsel review pending in the lawyer packet] The DOB is\n // persisted at EXACTLY ONE point: becomeArtisanCreator ('artisanOnboarding'). Registration\n // and the teen→adult upgrade derive the bracket server-side and persist NO DOB for anyone\n // (the register screen's \"It is not stored\" notice is literally true). Rationale: the\n // payout-KYC cross-check (compare to Stripe KYC DOB before paying out) only ever applies to\n // artisans — the money boundary — so collection happens there, with UI copy warning the\n // DOB must match the user's future payout identity. Server re-derives 18+ from the entered\n // DOB; an under-18 derivation rejects with a failure audit and stores nothing. PII —\n // privateData only (Invariant #5); same no-log posture as the raw DOB (scrubber + canary).\n attestedDateOfBirth: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/).optional(), // 'YYYY-MM-DD'\n attestedDobRecordedAt: z.number().optional(), // epoch ms\n attestedDobSource: z.enum(['artisanOnboarding']).optional(),\n}).strict();\nexport type UserPrivateDataAgeFields = z.infer<typeof UserPrivateDataAgeFieldsSchema>;\n\n/** The raw shape (for the orchestrator to `.extend(...)` / spread into\n * `UserPrivateDataSchema` without re-wrapping). */\nexport const userPrivateDataAgeFieldsShape = {\n accountType: AgeBracketSchema,\n is18Plus: z.boolean(),\n agePolicyVersion: z.string().min(1),\n accountCapabilityVersion: z.number().int(),\n ageAttestedAt: z.number(),\n adultUpgradedAt: z.number().optional(),\n ageManualCorrection: UserPrivateDataAgeManualCorrectionSchema.optional(),\n attestedDateOfBirth: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/).optional(),\n attestedDobRecordedAt: z.number().optional(),\n attestedDobSource: z.enum(['artisanOnboarding']).optional(),\n} as const;\n\n// ===========================================================================\n// A7 — Registration-completion RESULT (uses the IMPORTED domain enum)\n//\n// `completeRegistration.ts` returns exactly one RegistrationCompletionOutcome. The\n// enum itself is the SINGLE SOURCE in ./foundation.js — re-exported here for cluster\n// convenience, NEVER redefined.\n// ===========================================================================\n\nexport { RegistrationCompletionOutcomeSchema } from './foundation.js';\nexport type { RegistrationCompletionOutcome } from './foundation.js';\n\n/** The result envelope `completeRegistration.ts` returns. `outcome` is the imported\n * domain enum (never a raw gRPC code); only this domain outcome feeds the orphan-Auth\n * deletion policy. */\nexport const RegistrationCompletionResultV1Schema = z.object({\n outcome: RegistrationCompletionOutcomeSchema,\n uid: z.string().min(1).optional(), // present on 'completed' / 'alreadyCompletedSameUid'\n}).strict();\nexport type RegistrationCompletionResultV1 = z.infer<typeof RegistrationCompletionResultV1Schema>;\n"]}
|
|
1
|
+
{"version":3,"file":"age.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/age.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — age attestation, registration nonce, and account age-fields\n// (Appendix A §A7 — \"Age (full contract)\" + the §A11 [H6] concrete AgePolicyConfigV1\n// default block).\n//\n// This cluster owns:\n// - `ageAttestationNonces/{nonceHash}` (AgeAttestationNonceV1) — the one-time,\n// 256-bit server-generated registration nonce. Only the SHA-256 of the nonce is\n// the doc id; the raw nonce appears only inside the signed token.\n// - The pinned `ageBracketAttestation` JWS payload-claims shape [M-09] — the DECODED\n// claims of the compact JWS (JWT, RFC 7519, alg=HS256) issued at /api/age/attest\n// and verified at /api/register/complete.\n// - The `__Secure-ttt_age_session` cookie spec [F13] (an exported const, NOT a doc).\n// - `AgePolicyConfigV1` (the `_config/agePolicy` singleton) + its pinned literal\n// default const (§A11 [H6]).\n// - The teen→adult `ageUpgradeAttestation` token shape.\n// - `UserPrivateDataAgeFieldsSchema` — the STANDALONE age-fields shape that the\n// orchestrator merges into `UserPrivateDataSchema` (privateData/{uid}). This file\n// does NOT edit user.ts.\n//\n// Every field/enum/optionality/bound is transcribed verbatim from the frozen spec\n// (docs/code_changes_needed/trust-and-safety/IMPLEMENTATION_PLAN.md, Appendix A) — no\n// invented values, no placeholders.\n//\n// `RegistrationCompletionOutcome` is the DOMAIN outcome that feeds the orphan-Auth\n// deletion policy; it is the SINGLE SOURCE in ./foundation.js and is IMPORTED here\n// (never redefined).\n//\n// Timestamp convention: epoch-MILLISECONDS via z.number() — EXCEPT the JWS token\n// claims `iat`/`exp`, which are epoch-SECONDS per JWT (RFC 7519); those are commented\n// at the claim.\n\nimport { z } from 'zod';\nimport { RegistrationCompletionOutcomeSchema } from './foundation.js';\n\n// ===========================================================================\n// A7 — ageAttestationNonces/{nonceHash} (AgeAttestationNonceV1)\n// One-time, 256-bit server-generated nonce. Only the nonce's SHA-256 is the doc id;\n// the raw nonce appears only inside the signed token. 10-minute TTL; one successful\n// consume, transactionally bound to the new Auth uid AND the requestSessionHash;\n// expired/used/unknown fails closed. Spent records auto-delete ~24h after consume/expiry\n// via a Firestore native-TTL policy on `ttlExpireAt` (F-018) — no scheduled reaper.\n// ===========================================================================\n\n/** Server-derived audience bracket — NEVER client-derived. */\nexport const AgeBracketSchema = z.enum(['teen', 'adult']);\nexport type AgeBracket = z.infer<typeof AgeBracketSchema>;\n\n/** Nonce lifecycle status. `expired`/`consumed`/unknown all fail closed at consume. */\nexport const AgeAttestationNonceStatusSchema = z.enum(['issued', 'consumed', 'expired']);\nexport type AgeAttestationNonceStatus = z.infer<typeof AgeAttestationNonceStatusSchema>;\n\n/** `ageAttestationNonces/{nonceHash}` — the registration attestation nonce record.\n * Doc id is the SHA-256 hex of the 256-bit server nonce (deterministic; the raw\n * nonce lives only in the signed token, never in Firestore). */\nexport const AgeAttestationNonceV1Schema = z.object({\n schemaVersion: z.literal(1),\n bracket: AgeBracketSchema, // SERVER-derived audience bracket\n policyVersion: z.string().min(1), // the agePolicyVersion in force when issued\n signingKeyVersion: z.string().min(1), // the versioned KMS/Secret-Manager key that signs the token (= JWS `kid`)\n requestSessionHash: z.string().min(1), // SHA-256 of the registering session/request marker — the binding (High-6 §D)\n issuedAt: z.number(), // epoch ms\n expiresAt: z.number(), // epoch ms; issuedAt + 10-min TTL\n consumedAt: z.number().optional(), // epoch ms; set on the one successful consume\n consumedByUid: z.string().min(1).optional(), // the new Auth uid this nonce was transactionally bound to\n status: AgeAttestationNonceStatusSchema,\n // [Q21.5 REVISED — DJ 2026-07-06] The nonce carries NO date of birth for ANY bracket.\n // Registration never persists a DOB (adult or teen — only the derived bracket survives);\n // the previous adult-bracket `dateOfBirth` carry field was removed. The ONLY place a DOB\n // is ever persisted is becomeArtisanCreator ('artisanOnboarding') — see\n // UserPrivateDataAgeFieldsSchema below. Raw DOBs remain no-log everywhere.\n // [F-018] Firestore NATIVE-TTL field. Set to a real Firestore `Timestamp` of (consume/expire time +\n // ~24h) at the moment the nonce becomes spent; a TTL policy on `ageAttestationNonces.ttlExpireAt`\n // then auto-deletes the spent single-use record (no scheduled reaper). DOCUMENTED EXCEPTION to this\n // file's epoch-ms-number convention: native TTL requires a real Timestamp, and this field is\n // WRITE-ONLY (never read by app code), so it is typed opaquely here (`z.unknown`) to avoid pulling a\n // firebase `Timestamp` type into the environment-agnostic ttt-core schema layer (the app writes it via\n // `admin.firestore.Timestamp.fromMillis`, mirroring notification-core's `expireAt`). Absent until spent.\n ttlExpireAt: z.unknown().optional(),\n}).strict();\nexport type AgeAttestationNonceV1 = z.infer<typeof AgeAttestationNonceV1Schema>;\n\n// ===========================================================================\n// A7 [M-09] — ageBracketAttestation JWS payload claims (the ONE pinned wire format)\n//\n// The token is a COMPACT JWS (JWT, RFC 7519) with alg=HS256, signed by the versioned\n// KMS/Secret-Manager key. The schema below validates the DECODED PAYLOAD CLAIMS only.\n//\n// JOSE header (NOT part of this schema — documented for the verifier):\n// { \"alg\": \"HS256\", \"typ\": \"JWT\", \"kid\": <signingKeyVersion> } // kid = the exact signingKeyVersion\n//\n// Serialization: standard JWS compact form\n// base64url(header) '.' base64url(payload) '.' base64url(sig)\n// the signature is base64url (no padding); claim names + types are EXACTLY as below\n// (no extra claims).\n//\n// Verification REQUIRES (fail-closed on any miss): valid HS256 signature under the key\n// named by `kid`; aud == \"ttt-register-complete\"; iss == \"ttt-age-attest\"; exp not\n// passed; sub matches the ageAttestationNonces doc being consumed; rsh matches the\n// request's requestSessionHash.\n//\n// `iat`/`exp` are epoch-SECONDS (per JWT), NOT epoch-millis like the rest of this file.\n// ===========================================================================\n\nexport const AgeBracketAttestationClaimsV1Schema = z.object({\n iss: z.literal('ttt-age-attest'), // issuer\n aud: z.literal('ttt-register-complete'), // AUDIENCE/purpose binding — /api/register/complete MUST verify aud\n sub: z.string().min(1), // the SHA-256 nonce hash (also the ageAttestationNonces doc id)\n iat: z.number().int(), // epoch SECONDS (per JWT)\n exp: z.number().int(), // epoch SECONDS (per JWT); exp = iat + 600 (10-min TTL)\n bkt: AgeBracketSchema, // the SERVER-derived bracket (never client-derived)\n pv: z.string().min(1), // agePolicyVersion string\n rsh: z.string().min(1), // sha256(cookieValue) — the session binding\n}).strict();\nexport type AgeBracketAttestationClaimsV1 = z.infer<typeof AgeBracketAttestationClaimsV1Schema>;\n\n// ===========================================================================\n// A7 [F13] — Age-session cookie spec (`__Secure-ttt_age_session`)\n//\n// Pinned cookie attributes. The cookie VALUE is a cryptographically-random value\n// generated per registration attempt; only requestSessionHash = sha256(cookieValue)\n// is stored (with the nonce) — the raw cookie value is NEVER persisted. A separate\n// non-unique UX marker may exist for display, but is NEVER the security binding.\n//\n// `Domain` is omitted (host-only) — represented here by `hostOnly: true`.\n// ===========================================================================\n\nexport const AGE_SESSION_COOKIE_SPEC = {\n name: '__Secure-ttt_age_session',\n hostOnly: true, // Domain attribute omitted → host-only cookie\n path: '/api',\n secure: true,\n httpOnly: true,\n sameSite: 'Strict',\n maxAgeSeconds: 600, // 10 min\n} as const;\n\n// ===========================================================================\n// A7 / A11 [H6] — AgePolicyConfigV1 (the `_config/agePolicy` singleton)\n//\n// The generic gRPC retryable/terminal code lists are REMOVED — deletion is driven\n// ONLY by the RegistrationCompletionOutcome domain enum (§A7). No raw gRPC code ever\n// deletes an account. noDeleteOutcomes / terminalDeletableOutcomes are typed against\n// the imported RegistrationCompletionOutcome enum so the two arrays can never drift\n// from the domain outcome set.\n// ===========================================================================\n\nexport const AgePolicyConfigV1Schema = z.object({\n agePolicyVersion: z.string().min(1),\n registrationGracePeriodMinutes: z.number().int(),\n cleanupSchedule: z.string().min(1), // cron expression for the orphan-Auth cleanup worker\n ageTokenTtlSeconds: z.number().int(), // [M-09] token TTL\n keyRetirementVerificationMinutes: z.number().int(), // [M-09] retired-signingKeyVersion verification window (> TTL so no live token is orphaned by a rotation)\n noDeleteOutcomes: z.array(RegistrationCompletionOutcomeSchema),\n terminalDeletableOutcomes: z.array(RegistrationCompletionOutcomeSchema),\n}).strict();\nexport type AgePolicyConfigV1 = z.infer<typeof AgePolicyConfigV1Schema>;\n\n/** The pinned literal default for `_config/agePolicy` (§A11 [H6] concrete config\n * values). Build defaults — transcribed verbatim from the frozen spec. */\nexport const DEFAULT_AGE_POLICY_CONFIG_V1: AgePolicyConfigV1 = {\n agePolicyVersion: '2026-06-19.general-audience.v1',\n registrationGracePeriodMinutes: 30,\n cleanupSchedule: '*/15 * * * *',\n ageTokenTtlSeconds: 600,\n keyRetirementVerificationMinutes: 15,\n noDeleteOutcomes: [\n 'completed',\n 'alreadyCompletedSameUid',\n 'retryableInfrastructureFailure',\n 'reauthenticationRequired',\n 'appCheckRetryRequired',\n 'privateDataConflict',\n ],\n terminalDeletableOutcomes: [\n 'nonceExpired',\n 'nonceUnknown',\n 'nonceConsumedDifferentUid',\n 'sessionHashMismatch',\n 'attestationSignatureInvalid',\n 'policyVersionRejected',\n ],\n};\n\n// ===========================================================================\n// A7 — teen→adult ageUpgradeAttestation token\n//\n// A SEPARATE token (not the registration nonce) issued to an authenticated,\n// recently-reauthenticated session. Binds uid + accountCapabilityVersion +\n// policyVersion + issued/expiry + nonce; consumed ONLY for that uid+version; never\n// the registration nonce, never cross-account.\n//\n// This is a token claims shape (decoded payload), NOT a stored Firestore doc.\n// ===========================================================================\n\nexport const AgeUpgradeAttestationV1Schema = z.object({\n uid: z.string().min(1), // the authenticated, recently-reauthenticated account\n accountCapabilityVersion: z.number().int(), // the capability version this upgrade is bound to\n policyVersion: z.string().min(1), // agePolicyVersion in force\n issuedAt: z.number(), // epoch ms\n expiresAt: z.number(), // epoch ms\n nonce: z.string().min(1), // single-use upgrade nonce (never the registration nonce; never cross-account)\n}).strict();\nexport type AgeUpgradeAttestationV1 = z.infer<typeof AgeUpgradeAttestationV1Schema>;\n\n// ===========================================================================\n// A7 — UserPrivateData age fields (STANDALONE shape for the orchestrator)\n//\n// These fields live on `privateData/{uid}` (server-write-only). They are exported as\n// a STANDALONE object shape so the orchestrator can merge them into\n// `UserPrivateDataSchema` in user.ts WITHOUT this file editing user.ts.\n// ===========================================================================\n\n/** Manual age-correction audit stub (who corrected, when, why) — embedded on the\n * private user data when a reviewer hand-corrects the recorded age state. */\nexport const UserPrivateDataAgeManualCorrectionSchema = z.object({\n at: z.number(), // epoch ms\n actorId: z.string().min(1),\n reason: z.string().min(1),\n}).strict();\nexport type UserPrivateDataAgeManualCorrection = z.infer<typeof UserPrivateDataAgeManualCorrectionSchema>;\n\n/** STANDALONE age-fields shape — the orchestrator merges these into\n * `UserPrivateDataSchema` (privateData/{uid}, server-write-only). Exported as a raw\n * object shape (NOT a z.object) so it can be spread into the canonical schema. */\nexport const UserPrivateDataAgeFieldsSchema = z.object({\n accountType: AgeBracketSchema, // 'teen' | 'adult'\n is18Plus: z.boolean(),\n agePolicyVersion: z.string().min(1),\n accountCapabilityVersion: z.number().int(),\n ageAttestedAt: z.number(), // epoch ms\n adultUpgradedAt: z.number().optional(), // epoch ms; set on a successful teen→adult upgrade\n ageManualCorrection: UserPrivateDataAgeManualCorrectionSchema.optional(),\n // [Q21.5 REVISED — DJ 2026-07-06, counsel review pending in the lawyer packet] The DOB is\n // persisted at EXACTLY ONE point: becomeArtisanCreator ('artisanOnboarding'). Registration\n // and the teen→adult upgrade derive the bracket server-side and persist NO DOB for anyone\n // (the register screen's \"It is not stored\" notice is literally true). Rationale: the\n // payout-KYC cross-check (compare to Stripe KYC DOB before paying out) only ever applies to\n // artisans — the money boundary — so collection happens there, with UI copy warning the\n // DOB must match the user's future payout identity. Server re-derives 18+ from the entered\n // DOB; an under-18 derivation rejects with a failure audit and stores nothing. PII —\n // privateData only (BACKEND-105); same no-log posture as the raw DOB (scrubber + canary).\n attestedDateOfBirth: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/).optional(), // 'YYYY-MM-DD'\n attestedDobRecordedAt: z.number().optional(), // epoch ms\n attestedDobSource: z.enum(['artisanOnboarding']).optional(),\n}).strict();\nexport type UserPrivateDataAgeFields = z.infer<typeof UserPrivateDataAgeFieldsSchema>;\n\n/** The raw shape (for the orchestrator to `.extend(...)` / spread into\n * `UserPrivateDataSchema` without re-wrapping). */\nexport const userPrivateDataAgeFieldsShape = {\n accountType: AgeBracketSchema,\n is18Plus: z.boolean(),\n agePolicyVersion: z.string().min(1),\n accountCapabilityVersion: z.number().int(),\n ageAttestedAt: z.number(),\n adultUpgradedAt: z.number().optional(),\n ageManualCorrection: UserPrivateDataAgeManualCorrectionSchema.optional(),\n attestedDateOfBirth: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/).optional(),\n attestedDobRecordedAt: z.number().optional(),\n attestedDobSource: z.enum(['artisanOnboarding']).optional(),\n} as const;\n\n// ===========================================================================\n// A7 — Registration-completion RESULT (uses the IMPORTED domain enum)\n//\n// `completeRegistration.ts` returns exactly one RegistrationCompletionOutcome. The\n// enum itself is the SINGLE SOURCE in ./foundation.js — re-exported here for cluster\n// convenience, NEVER redefined.\n// ===========================================================================\n\nexport { RegistrationCompletionOutcomeSchema } from './foundation.js';\nexport type { RegistrationCompletionOutcome } from './foundation.js';\n\n/** The result envelope `completeRegistration.ts` returns. `outcome` is the imported\n * domain enum (never a raw gRPC code); only this domain outcome feeds the orphan-Auth\n * deletion policy. */\nexport const RegistrationCompletionResultV1Schema = z.object({\n outcome: RegistrationCompletionOutcomeSchema,\n uid: z.string().min(1).optional(), // present on 'completed' / 'alreadyCompletedSameUid'\n}).strict();\nexport type RegistrationCompletionResultV1 = z.infer<typeof RegistrationCompletionResultV1Schema>;\n"]}
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
import { z } from 'zod';
|
|
28
28
|
import { MediaOriginLineageV1Schema } from '../media-assets.js';
|
|
29
29
|
// ===========================================================================
|
|
30
|
-
// §A4 manifest / communication array caps — the ONE named declaration (
|
|
30
|
+
// §A4 manifest / communication array caps — the ONE named declaration (ARCH-102).
|
|
31
31
|
// Every `.max(...)` bound below derives from these; the app's evidence-manifest
|
|
32
32
|
// writer imports the SAME constants for its `bound(...)` checks so the schema and the
|
|
33
33
|
// writer can never drift to two different numbers.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/evidence.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — the evidence cluster (Appendix A §A4, Finding-H5 / Finding-M2).\n//\n// Two collections:\n// - `safetyEvidenceManifests/{manifestId}` = SafetyEvidenceManifestV1 — an\n// IMMUTABLE, versioned manifest. Finding-H5: a manifest is NO LONGER\n// media-shaped — a `sourceKind` discriminator ('media'|'communication'|\n// 'externalFact') selects WHICH sub-object is present. No manifest may carry\n// a null/placeholder media object.\n// - `safetyEvidenceJobs/{jobId}` = SafetyEvidenceJobV1 — the capture/verify/\n// disposition saga row (Finding-M2: `commandId` + terminal timestamps; the\n// `verified` status is disambiguated as a (phase, status) PAIR, never a bare\n// status) with two subcollections: …/items/{itemId} and\n// …/disposition/{locationId}.\n//\n// Every shape here is transcribed verbatim from docs/code_changes_needed/\n// trust-and-safety/IMPLEMENTATION_PLAN.md Appendix A §A4 — no invented values, no\n// placeholders.\n//\n// SHARED media lineage comes from ../media-assets.js (the single canonical lineage\n// used by media, CSAM, and safety); it is NEVER redefined here.\n//\n// Collection note: this cluster introduces TWO NEW Firestore collections plus two\n// subcollections under `safetyEvidenceJobs`. Wiring collections.ts /\n// path-builders.ts / registry.ts is deferred to the app leg (the orchestrator binds\n// the schemas + path builders there); the deterministic doc-id shapes are\n// documented on each schema below.\n\nimport { z } from 'zod';\nimport { MediaOriginLineageV1Schema } from '../media-assets.js';\n\n// ===========================================================================\n// §A4 manifest / communication array caps — the ONE named declaration (Rule 36).\n// Every `.max(...)` bound below derives from these; the app's evidence-manifest\n// writer imports the SAME constants for its `bound(...)` checks so the schema and the\n// writer can never drift to two different numbers.\n// ===========================================================================\n\n/** MAX variants[] on a media manifest (§A4). */\nexport const MAX_MANIFEST_VARIANTS = 64;\n/** MAX provenanceRefs[] (eventProvenance ids promoted into the case) on a manifest (§A4). */\nexport const MAX_MANIFEST_PROVENANCE_REFS = 64;\n/** MAX ncmecReceiptRefs[] on a manifest (§A4). */\nexport const MAX_MANIFEST_NCMEC_RECEIPTS = 32;\n/** MAX attachmentItemIds[] on a communication manifest (§A4). */\nexport const MAX_COMMUNICATION_ATTACHMENTS = 256;\n\n// ===========================================================================\n// §A4 — safetyEvidenceManifests/{manifestId} = SafetyEvidenceManifestV1\n// (Finding-H5). IMMUTABLE, versioned. `sourceKind` selects the present sub-object.\n// ===========================================================================\n\n/** The source-kind discriminator (Finding-H5). Selects WHICH sub-object is present\n * on the manifest: `media` → original/variants/lineage/evidenceCopy;\n * `communication` → communication; `externalFact` → externalFact. */\nexport const SafetyEvidenceSourceKindSchema = z.enum([\n 'media',\n 'communication',\n 'externalFact',\n]);\nexport type SafetyEvidenceSourceKind = z.infer<typeof SafetyEvidenceSourceKindSchema>;\n\n/** §A4 `original` — present ONLY when sourceKind='media'. The captured original\n * object descriptor (never a serving URL). */\nexport const SafetyEvidenceOriginalV1Schema = z.object({\n bucket: z.string().min(1),\n key: z.string().min(1),\n generation: z.string().min(1),\n contentType: z.string().min(1),\n filename: z.string().min(1).optional(),\n sizeBytes: z.number(),\n md5: z.string().min(1),\n sha256: z.string().min(1),\n capturedAt: z.number(),\n}).strict();\nexport type SafetyEvidenceOriginalV1 = z.infer<typeof SafetyEvidenceOriginalV1Schema>;\n\n/** §A4 `variants[]` — media only; MAX 64. */\nexport const SafetyEvidenceVariantV1Schema = z.object({\n variantKey: z.string().min(1),\n sha256: z.string().min(1),\n sizeBytes: z.number(),\n}).strict();\nexport type SafetyEvidenceVariantV1 = z.infer<typeof SafetyEvidenceVariantV1Schema>;\n\n/** §A4 `communication` — present ONLY when sourceKind='communication'.\n * `attachmentItemIds` MAX 256. */\nexport const SafetyEvidenceCommunicationV1Schema = z.object({\n channelId: z.string().min(1),\n messageSeqStart: z.number(),\n messageSeqEnd: z.number(),\n transcriptObjectRef: z.string().min(1),\n attachmentItemIds: z.array(z.string().min(1)).max(MAX_COMMUNICATION_ATTACHMENTS),\n}).strict();\nexport type SafetyEvidenceCommunicationV1 = z.infer<typeof SafetyEvidenceCommunicationV1Schema>;\n\n/** §A4 externalFact `factKind`. */\nexport const SafetyEvidenceExternalFactKindSchema = z.enum([\n 'lawEnforcement',\n 'thirdPartyReport',\n 'operatorKnowledge',\n 'other',\n]);\nexport type SafetyEvidenceExternalFactKind = z.infer<typeof SafetyEvidenceExternalFactKindSchema>;\n\n/** §A4 `externalFact` — present ONLY when sourceKind='externalFact'. */\nexport const SafetyEvidenceExternalFactV1Schema = z.object({\n factKind: SafetyEvidenceExternalFactKindSchema,\n narrativeRef: z.string().min(1),\n establishedActualKnowledgeAt: z.number().optional(),\n sourceContactRef: z.string().min(1).optional(),\n}).strict();\nexport type SafetyEvidenceExternalFactV1 = z.infer<typeof SafetyEvidenceExternalFactV1Schema>;\n\n/** §A4 `detector` — never the raw hash. */\nexport const SafetyEvidenceDetectorV1Schema = z.object({\n source: z.string().min(1),\n listId: z.string().min(1),\n sdkVersion: z.string().min(1),\n requestTraceId: z.string().min(1),\n matchResult: z.string().min(1),\n}).strict();\nexport type SafetyEvidenceDetectorV1 = z.infer<typeof SafetyEvidenceDetectorV1Schema>;\n\n/** §A4 `evidenceCopy` — media only; the verified evidence-vault copy descriptor. */\nexport const SafetyEvidenceCopyV1Schema = z.object({\n destinationBucket: z.string().min(1),\n destinationKey: z.string().min(1),\n keyVersion: z.string().min(1),\n verifyMethod: z.string().min(1),\n verifyResult: z.string().min(1),\n}).strict();\nexport type SafetyEvidenceCopyV1 = z.infer<typeof SafetyEvidenceCopyV1Schema>;\n\n/** §A4 `reporter` — restricted; segregated from ordinary admin views. */\nexport const SafetyEvidenceReporterV1Schema = z.object({\n reporterUidRef: z.string().min(1),\n narrativeRef: z.string().min(1),\n}).strict();\nexport type SafetyEvidenceReporterV1 = z.infer<typeof SafetyEvidenceReporterV1Schema>;\n\n/**\n * `safetyEvidenceManifests/{manifestId}` — IMMUTABLE, versioned\n * SafetyEvidenceManifestV1 (Finding-H5). Doc id is the deterministic `manifestId`.\n *\n * **Invariant (H5) — enforced by the superRefine below:** no manifest may require a\n * null/placeholder media object. The sub-objects are present ONLY for their matching\n * `sourceKind`:\n * - sourceKind='media' → `original` + `lineage` REQUIRED; `variants`/\n * `evidenceCopy` allowed; `communication`/\n * `externalFact` MUST be absent.\n * - sourceKind='communication' → `communication` REQUIRED; `original`/`variants`/\n * `lineage`/`evidenceCopy`/`externalFact` MUST be absent.\n * - sourceKind='externalFact' → `externalFact` REQUIRED; `original`/`variants`/\n * `lineage`/`evidenceCopy`/`communication` MUST be absent.\n *\n * Lineage-keyed auto-action + dedup (incident-wide blocking by `rootIngestId`,\n * auto-ban of `originatingUploaderUid`) apply ONLY to sourceKind='media' — a\n * communication/externalFact manifest carries no lineage and is multi-subject via\n * the case `…/accounts` subcollection (`subjectAccountsRef`), never a synthesized\n * uploader.\n */\nexport const SafetyEvidenceManifestV1Schema = z.object({\n schemaVersion: z.literal(1),\n manifestId: z.string().min(1),\n caseId: z.string().min(1),\n createdAt: z.number(),\n sourceKind: SafetyEvidenceSourceKindSchema, // REQUIRED — selects the present sub-object\n original: SafetyEvidenceOriginalV1Schema.optional(), // present ONLY when sourceKind='media'\n variants: z.array(SafetyEvidenceVariantV1Schema).max(MAX_MANIFEST_VARIANTS).optional(), // media only\n lineage: MediaOriginLineageV1Schema.optional(), // present ONLY when sourceKind='media'\n communication: SafetyEvidenceCommunicationV1Schema.optional(), // present ONLY when sourceKind='communication'\n externalFact: SafetyEvidenceExternalFactV1Schema.optional(), // present ONLY when sourceKind='externalFact'\n // multi-subject lives in the case childSafetyCases/{caseId}/accounts subcollection\n // (no fake uploader on the manifest); this points at …/accounts:\n subjectAccountsRef: z.string().min(1),\n provenanceRefs: z.array(z.string().min(1)).max(MAX_MANIFEST_PROVENANCE_REFS), // eventProvenance ids promoted into the case\n contentDocSnapshotRef: z.string().min(1).optional(),\n contentDocRevision: z.number().optional(),\n detector: SafetyEvidenceDetectorV1Schema.optional(), // never the raw hash\n evidenceCopy: SafetyEvidenceCopyV1Schema.optional(), // media only\n reporter: SafetyEvidenceReporterV1Schema.optional(), // restricted; segregated from ordinary admin views\n ncmecReceiptRefs: z.array(z.string().min(1)).max(MAX_MANIFEST_NCMEC_RECEIPTS),\n}).strict().superRefine((val, ctx) => {\n // H5 invariant: the sourceKind→present-object set. `media` requires original +\n // lineage and forbids communication/externalFact; `communication` requires\n // communication and forbids all media-only fields + externalFact; `externalFact`\n // requires externalFact and forbids all media-only fields + communication.\n const present = (field: string) =>\n ctx.addIssue({ code: 'custom', path: [field], message: `${field} is only allowed when sourceKind matches` });\n const missing = (field: string) =>\n ctx.addIssue({ code: 'custom', path: [field], message: `${field} is required for this sourceKind` });\n\n if (val.sourceKind === 'media') {\n if (val.original === undefined) missing('original');\n if (val.lineage === undefined) missing('lineage');\n if (val.communication !== undefined) present('communication');\n if (val.externalFact !== undefined) present('externalFact');\n } else if (val.sourceKind === 'communication') {\n if (val.communication === undefined) missing('communication');\n if (val.original !== undefined) present('original');\n if (val.variants !== undefined) present('variants');\n if (val.lineage !== undefined) present('lineage');\n if (val.evidenceCopy !== undefined) present('evidenceCopy');\n if (val.externalFact !== undefined) present('externalFact');\n } else {\n // externalFact\n if (val.externalFact === undefined) missing('externalFact');\n if (val.original !== undefined) present('original');\n if (val.variants !== undefined) present('variants');\n if (val.lineage !== undefined) present('lineage');\n if (val.evidenceCopy !== undefined) present('evidenceCopy');\n if (val.communication !== undefined) present('communication');\n }\n});\nexport type SafetyEvidenceManifestV1 = z.infer<typeof SafetyEvidenceManifestV1Schema>;\n\n// ===========================================================================\n// §A4 — safetyEvidenceJobs/{jobId} = SafetyEvidenceJobV1 (Finding-M2).\n// `verified` is disambiguated as a (phase, status) PAIR, never a bare status.\n// `commandId` is deterministic per (jobId, phase). One worker per phase drives:\n// capture worker → (capture: pending → running → verified) | (capture: deadLetter)\n// verify worker → (verify: pending → running → verified)\n// disposition worker → (disposition: pending → running → disposed) | (disposition: deadLetter)\n// (disposition runs only after preservationStatus=dispositionPending). Terminal\n// timestamps: completedAt on (capture|verify, verified), disposedAt on\n// (disposition, disposed), deadLetterAt on any deadLetter.\n// ===========================================================================\n\n/** §A4 job phase — one worker per phase. */\nexport const SafetyEvidenceJobPhaseSchema = z.enum([\n 'capture',\n 'verify',\n 'disposition',\n]);\nexport type SafetyEvidenceJobPhase = z.infer<typeof SafetyEvidenceJobPhaseSchema>;\n\n/** §A4 job status — disambiguated by the (phase, status) pairing rules above; never\n * a bare status. */\nexport const SafetyEvidenceJobStatusSchema = z.enum([\n 'pending',\n 'running',\n 'verified',\n 'disposed',\n 'deadLetter',\n]);\nexport type SafetyEvidenceJobStatus = z.infer<typeof SafetyEvidenceJobStatusSchema>;\n\n/** `safetyEvidenceJobs/{jobId}` — the capture/verify/disposition saga row\n * (Finding-M2). Doc id is the deterministic `jobId`. `commandId` is deterministic\n * per (jobId, phase) — idempotent + replayed by commandId. */\nexport const SafetyEvidenceJobV1Schema = z.object({\n schemaVersion: z.literal(1),\n jobId: z.string().min(1),\n caseId: z.string().min(1),\n phase: SafetyEvidenceJobPhaseSchema,\n commandId: z.string().min(1), // deterministic per (jobId, phase)\n status: SafetyEvidenceJobStatusSchema,\n attemptCount: z.number(),\n nextAttemptAt: z.number(),\n leaseOwner: z.string().min(1).optional(),\n leaseExpiresAt: z.number().optional(),\n lastErrorCode: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n completedAt: z.number().optional(), // (capture|verify, verified)\n disposedAt: z.number().optional(), // (disposition, disposed)\n deadLetterAt: z.number().optional(), // any deadLetter\n}).strict();\nexport type SafetyEvidenceJobV1 = z.infer<typeof SafetyEvidenceJobV1Schema>;\n\n// ===========================================================================\n// §A4 subcollections under a job\n// ===========================================================================\n\n/** §A4 job-item role — the source object vs the destination (evidence-copy) object. */\nexport const SafetyEvidenceJobItemRoleSchema = z.enum(['source', 'destination']);\nexport type SafetyEvidenceJobItemRole = z.infer<typeof SafetyEvidenceJobItemRoleSchema>;\n\n/** §A4 job-item verify result. */\nexport const SafetyEvidenceJobItemVerifyResultSchema = z.enum(['pending', 'ok', 'mismatch']);\nexport type SafetyEvidenceJobItemVerifyResult = z.infer<typeof SafetyEvidenceJobItemVerifyResultSchema>;\n\n/** `safetyEvidenceJobs/{jobId}/items/{itemId}` — per-object source/destination row.\n * Doc id is the `itemId`. */\nexport const SafetyEvidenceJobItemV1Schema = z.object({\n role: SafetyEvidenceJobItemRoleSchema,\n bucket: z.string().min(1),\n key: z.string().min(1),\n generation: z.string().min(1).optional(),\n sizeBytes: z.number(),\n sha256: z.string().min(1),\n md5: z.string().min(1).optional(),\n verifyResult: SafetyEvidenceJobItemVerifyResultSchema,\n}).strict();\nexport type SafetyEvidenceJobItemV1 = z.infer<typeof SafetyEvidenceJobItemV1Schema>;\n\n/** §A4 disposition method (per evidence location). */\nexport const SafetyEvidenceDispositionMethodSchema = z.enum(['delete', 'cryptoErase']);\nexport type SafetyEvidenceDispositionMethod = z.infer<typeof SafetyEvidenceDispositionMethodSchema>;\n\n/** §A4 disposition result (per evidence location). */\nexport const SafetyEvidenceDispositionResultSchema = z.enum(['gone', 'leftover']);\nexport type SafetyEvidenceDispositionResult = z.infer<typeof SafetyEvidenceDispositionResultSchema>;\n\n/** `safetyEvidenceJobs/{jobId}/disposition/{locationId}` — per-evidence-location\n * deletion-verification record. Doc id is the `locationId`.\n *\n * [M-5] This IS the durable hard-deletion attestation body: the disposition worker runs only after\n * the case reaches `preservationStatus:'dispositionPending'` (every hold ref released + a reviewed\n * disposition job), and records `method` + `verifiedAt` + `result`. Because soft-delete is DISABLED\n * on the evidence bucket, `result:'gone'` attests a verified TRUE hard-deletion (there is no\n * soft-delete/lifecycle tombstone to model — no `softDeletedAt`/`hardDeleteTime`). `generation`\n * pins the exact object generation that was destroyed, so a later object re-created at the same\n * bucket/key (a new generation) is never falsely attested as this destruction. */\nexport const SafetyEvidenceDispositionV1Schema = z.object({\n bucket: z.string().min(1),\n key: z.string().min(1),\n // [M-5] the exact object generation this record attests destroyed — pins the attestation to a\n // single immutable object version so a same-key re-upload (new generation) is not covered by it.\n // Optional: an object with no generation concept (or a leftover with none read) omits it.\n generation: z.string().min(1).optional(),\n method: SafetyEvidenceDispositionMethodSchema,\n verifiedAt: z.number(),\n result: SafetyEvidenceDispositionResultSchema,\n leftoverDetail: z.string().min(1).optional(),\n}).strict();\nexport type SafetyEvidenceDispositionV1 = z.infer<typeof SafetyEvidenceDispositionV1Schema>;\n"]}
|
|
1
|
+
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/evidence.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — the evidence cluster (Appendix A §A4, Finding-H5 / Finding-M2).\n//\n// Two collections:\n// - `safetyEvidenceManifests/{manifestId}` = SafetyEvidenceManifestV1 — an\n// IMMUTABLE, versioned manifest. Finding-H5: a manifest is NO LONGER\n// media-shaped — a `sourceKind` discriminator ('media'|'communication'|\n// 'externalFact') selects WHICH sub-object is present. No manifest may carry\n// a null/placeholder media object.\n// - `safetyEvidenceJobs/{jobId}` = SafetyEvidenceJobV1 — the capture/verify/\n// disposition saga row (Finding-M2: `commandId` + terminal timestamps; the\n// `verified` status is disambiguated as a (phase, status) PAIR, never a bare\n// status) with two subcollections: …/items/{itemId} and\n// …/disposition/{locationId}.\n//\n// Every shape here is transcribed verbatim from docs/code_changes_needed/\n// trust-and-safety/IMPLEMENTATION_PLAN.md Appendix A §A4 — no invented values, no\n// placeholders.\n//\n// SHARED media lineage comes from ../media-assets.js (the single canonical lineage\n// used by media, CSAM, and safety); it is NEVER redefined here.\n//\n// Collection note: this cluster introduces TWO NEW Firestore collections plus two\n// subcollections under `safetyEvidenceJobs`. Wiring collections.ts /\n// path-builders.ts / registry.ts is deferred to the app leg (the orchestrator binds\n// the schemas + path builders there); the deterministic doc-id shapes are\n// documented on each schema below.\n\nimport { z } from 'zod';\nimport { MediaOriginLineageV1Schema } from '../media-assets.js';\n\n// ===========================================================================\n// §A4 manifest / communication array caps — the ONE named declaration (ARCH-102).\n// Every `.max(...)` bound below derives from these; the app's evidence-manifest\n// writer imports the SAME constants for its `bound(...)` checks so the schema and the\n// writer can never drift to two different numbers.\n// ===========================================================================\n\n/** MAX variants[] on a media manifest (§A4). */\nexport const MAX_MANIFEST_VARIANTS = 64;\n/** MAX provenanceRefs[] (eventProvenance ids promoted into the case) on a manifest (§A4). */\nexport const MAX_MANIFEST_PROVENANCE_REFS = 64;\n/** MAX ncmecReceiptRefs[] on a manifest (§A4). */\nexport const MAX_MANIFEST_NCMEC_RECEIPTS = 32;\n/** MAX attachmentItemIds[] on a communication manifest (§A4). */\nexport const MAX_COMMUNICATION_ATTACHMENTS = 256;\n\n// ===========================================================================\n// §A4 — safetyEvidenceManifests/{manifestId} = SafetyEvidenceManifestV1\n// (Finding-H5). IMMUTABLE, versioned. `sourceKind` selects the present sub-object.\n// ===========================================================================\n\n/** The source-kind discriminator (Finding-H5). Selects WHICH sub-object is present\n * on the manifest: `media` → original/variants/lineage/evidenceCopy;\n * `communication` → communication; `externalFact` → externalFact. */\nexport const SafetyEvidenceSourceKindSchema = z.enum([\n 'media',\n 'communication',\n 'externalFact',\n]);\nexport type SafetyEvidenceSourceKind = z.infer<typeof SafetyEvidenceSourceKindSchema>;\n\n/** §A4 `original` — present ONLY when sourceKind='media'. The captured original\n * object descriptor (never a serving URL). */\nexport const SafetyEvidenceOriginalV1Schema = z.object({\n bucket: z.string().min(1),\n key: z.string().min(1),\n generation: z.string().min(1),\n contentType: z.string().min(1),\n filename: z.string().min(1).optional(),\n sizeBytes: z.number(),\n md5: z.string().min(1),\n sha256: z.string().min(1),\n capturedAt: z.number(),\n}).strict();\nexport type SafetyEvidenceOriginalV1 = z.infer<typeof SafetyEvidenceOriginalV1Schema>;\n\n/** §A4 `variants[]` — media only; MAX 64. */\nexport const SafetyEvidenceVariantV1Schema = z.object({\n variantKey: z.string().min(1),\n sha256: z.string().min(1),\n sizeBytes: z.number(),\n}).strict();\nexport type SafetyEvidenceVariantV1 = z.infer<typeof SafetyEvidenceVariantV1Schema>;\n\n/** §A4 `communication` — present ONLY when sourceKind='communication'.\n * `attachmentItemIds` MAX 256. */\nexport const SafetyEvidenceCommunicationV1Schema = z.object({\n channelId: z.string().min(1),\n messageSeqStart: z.number(),\n messageSeqEnd: z.number(),\n transcriptObjectRef: z.string().min(1),\n attachmentItemIds: z.array(z.string().min(1)).max(MAX_COMMUNICATION_ATTACHMENTS),\n}).strict();\nexport type SafetyEvidenceCommunicationV1 = z.infer<typeof SafetyEvidenceCommunicationV1Schema>;\n\n/** §A4 externalFact `factKind`. */\nexport const SafetyEvidenceExternalFactKindSchema = z.enum([\n 'lawEnforcement',\n 'thirdPartyReport',\n 'operatorKnowledge',\n 'other',\n]);\nexport type SafetyEvidenceExternalFactKind = z.infer<typeof SafetyEvidenceExternalFactKindSchema>;\n\n/** §A4 `externalFact` — present ONLY when sourceKind='externalFact'. */\nexport const SafetyEvidenceExternalFactV1Schema = z.object({\n factKind: SafetyEvidenceExternalFactKindSchema,\n narrativeRef: z.string().min(1),\n establishedActualKnowledgeAt: z.number().optional(),\n sourceContactRef: z.string().min(1).optional(),\n}).strict();\nexport type SafetyEvidenceExternalFactV1 = z.infer<typeof SafetyEvidenceExternalFactV1Schema>;\n\n/** §A4 `detector` — never the raw hash. */\nexport const SafetyEvidenceDetectorV1Schema = z.object({\n source: z.string().min(1),\n listId: z.string().min(1),\n sdkVersion: z.string().min(1),\n requestTraceId: z.string().min(1),\n matchResult: z.string().min(1),\n}).strict();\nexport type SafetyEvidenceDetectorV1 = z.infer<typeof SafetyEvidenceDetectorV1Schema>;\n\n/** §A4 `evidenceCopy` — media only; the verified evidence-vault copy descriptor. */\nexport const SafetyEvidenceCopyV1Schema = z.object({\n destinationBucket: z.string().min(1),\n destinationKey: z.string().min(1),\n keyVersion: z.string().min(1),\n verifyMethod: z.string().min(1),\n verifyResult: z.string().min(1),\n}).strict();\nexport type SafetyEvidenceCopyV1 = z.infer<typeof SafetyEvidenceCopyV1Schema>;\n\n/** §A4 `reporter` — restricted; segregated from ordinary admin views. */\nexport const SafetyEvidenceReporterV1Schema = z.object({\n reporterUidRef: z.string().min(1),\n narrativeRef: z.string().min(1),\n}).strict();\nexport type SafetyEvidenceReporterV1 = z.infer<typeof SafetyEvidenceReporterV1Schema>;\n\n/**\n * `safetyEvidenceManifests/{manifestId}` — IMMUTABLE, versioned\n * SafetyEvidenceManifestV1 (Finding-H5). Doc id is the deterministic `manifestId`.\n *\n * **Invariant (H5) — enforced by the superRefine below:** no manifest may require a\n * null/placeholder media object. The sub-objects are present ONLY for their matching\n * `sourceKind`:\n * - sourceKind='media' → `original` + `lineage` REQUIRED; `variants`/\n * `evidenceCopy` allowed; `communication`/\n * `externalFact` MUST be absent.\n * - sourceKind='communication' → `communication` REQUIRED; `original`/`variants`/\n * `lineage`/`evidenceCopy`/`externalFact` MUST be absent.\n * - sourceKind='externalFact' → `externalFact` REQUIRED; `original`/`variants`/\n * `lineage`/`evidenceCopy`/`communication` MUST be absent.\n *\n * Lineage-keyed auto-action + dedup (incident-wide blocking by `rootIngestId`,\n * auto-ban of `originatingUploaderUid`) apply ONLY to sourceKind='media' — a\n * communication/externalFact manifest carries no lineage and is multi-subject via\n * the case `…/accounts` subcollection (`subjectAccountsRef`), never a synthesized\n * uploader.\n */\nexport const SafetyEvidenceManifestV1Schema = z.object({\n schemaVersion: z.literal(1),\n manifestId: z.string().min(1),\n caseId: z.string().min(1),\n createdAt: z.number(),\n sourceKind: SafetyEvidenceSourceKindSchema, // REQUIRED — selects the present sub-object\n original: SafetyEvidenceOriginalV1Schema.optional(), // present ONLY when sourceKind='media'\n variants: z.array(SafetyEvidenceVariantV1Schema).max(MAX_MANIFEST_VARIANTS).optional(), // media only\n lineage: MediaOriginLineageV1Schema.optional(), // present ONLY when sourceKind='media'\n communication: SafetyEvidenceCommunicationV1Schema.optional(), // present ONLY when sourceKind='communication'\n externalFact: SafetyEvidenceExternalFactV1Schema.optional(), // present ONLY when sourceKind='externalFact'\n // multi-subject lives in the case childSafetyCases/{caseId}/accounts subcollection\n // (no fake uploader on the manifest); this points at …/accounts:\n subjectAccountsRef: z.string().min(1),\n provenanceRefs: z.array(z.string().min(1)).max(MAX_MANIFEST_PROVENANCE_REFS), // eventProvenance ids promoted into the case\n contentDocSnapshotRef: z.string().min(1).optional(),\n contentDocRevision: z.number().optional(),\n detector: SafetyEvidenceDetectorV1Schema.optional(), // never the raw hash\n evidenceCopy: SafetyEvidenceCopyV1Schema.optional(), // media only\n reporter: SafetyEvidenceReporterV1Schema.optional(), // restricted; segregated from ordinary admin views\n ncmecReceiptRefs: z.array(z.string().min(1)).max(MAX_MANIFEST_NCMEC_RECEIPTS),\n}).strict().superRefine((val, ctx) => {\n // H5 invariant: the sourceKind→present-object set. `media` requires original +\n // lineage and forbids communication/externalFact; `communication` requires\n // communication and forbids all media-only fields + externalFact; `externalFact`\n // requires externalFact and forbids all media-only fields + communication.\n const present = (field: string) =>\n ctx.addIssue({ code: 'custom', path: [field], message: `${field} is only allowed when sourceKind matches` });\n const missing = (field: string) =>\n ctx.addIssue({ code: 'custom', path: [field], message: `${field} is required for this sourceKind` });\n\n if (val.sourceKind === 'media') {\n if (val.original === undefined) missing('original');\n if (val.lineage === undefined) missing('lineage');\n if (val.communication !== undefined) present('communication');\n if (val.externalFact !== undefined) present('externalFact');\n } else if (val.sourceKind === 'communication') {\n if (val.communication === undefined) missing('communication');\n if (val.original !== undefined) present('original');\n if (val.variants !== undefined) present('variants');\n if (val.lineage !== undefined) present('lineage');\n if (val.evidenceCopy !== undefined) present('evidenceCopy');\n if (val.externalFact !== undefined) present('externalFact');\n } else {\n // externalFact\n if (val.externalFact === undefined) missing('externalFact');\n if (val.original !== undefined) present('original');\n if (val.variants !== undefined) present('variants');\n if (val.lineage !== undefined) present('lineage');\n if (val.evidenceCopy !== undefined) present('evidenceCopy');\n if (val.communication !== undefined) present('communication');\n }\n});\nexport type SafetyEvidenceManifestV1 = z.infer<typeof SafetyEvidenceManifestV1Schema>;\n\n// ===========================================================================\n// §A4 — safetyEvidenceJobs/{jobId} = SafetyEvidenceJobV1 (Finding-M2).\n// `verified` is disambiguated as a (phase, status) PAIR, never a bare status.\n// `commandId` is deterministic per (jobId, phase). One worker per phase drives:\n// capture worker → (capture: pending → running → verified) | (capture: deadLetter)\n// verify worker → (verify: pending → running → verified)\n// disposition worker → (disposition: pending → running → disposed) | (disposition: deadLetter)\n// (disposition runs only after preservationStatus=dispositionPending). Terminal\n// timestamps: completedAt on (capture|verify, verified), disposedAt on\n// (disposition, disposed), deadLetterAt on any deadLetter.\n// ===========================================================================\n\n/** §A4 job phase — one worker per phase. */\nexport const SafetyEvidenceJobPhaseSchema = z.enum([\n 'capture',\n 'verify',\n 'disposition',\n]);\nexport type SafetyEvidenceJobPhase = z.infer<typeof SafetyEvidenceJobPhaseSchema>;\n\n/** §A4 job status — disambiguated by the (phase, status) pairing rules above; never\n * a bare status. */\nexport const SafetyEvidenceJobStatusSchema = z.enum([\n 'pending',\n 'running',\n 'verified',\n 'disposed',\n 'deadLetter',\n]);\nexport type SafetyEvidenceJobStatus = z.infer<typeof SafetyEvidenceJobStatusSchema>;\n\n/** `safetyEvidenceJobs/{jobId}` — the capture/verify/disposition saga row\n * (Finding-M2). Doc id is the deterministic `jobId`. `commandId` is deterministic\n * per (jobId, phase) — idempotent + replayed by commandId. */\nexport const SafetyEvidenceJobV1Schema = z.object({\n schemaVersion: z.literal(1),\n jobId: z.string().min(1),\n caseId: z.string().min(1),\n phase: SafetyEvidenceJobPhaseSchema,\n commandId: z.string().min(1), // deterministic per (jobId, phase)\n status: SafetyEvidenceJobStatusSchema,\n attemptCount: z.number(),\n nextAttemptAt: z.number(),\n leaseOwner: z.string().min(1).optional(),\n leaseExpiresAt: z.number().optional(),\n lastErrorCode: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n completedAt: z.number().optional(), // (capture|verify, verified)\n disposedAt: z.number().optional(), // (disposition, disposed)\n deadLetterAt: z.number().optional(), // any deadLetter\n}).strict();\nexport type SafetyEvidenceJobV1 = z.infer<typeof SafetyEvidenceJobV1Schema>;\n\n// ===========================================================================\n// §A4 subcollections under a job\n// ===========================================================================\n\n/** §A4 job-item role — the source object vs the destination (evidence-copy) object. */\nexport const SafetyEvidenceJobItemRoleSchema = z.enum(['source', 'destination']);\nexport type SafetyEvidenceJobItemRole = z.infer<typeof SafetyEvidenceJobItemRoleSchema>;\n\n/** §A4 job-item verify result. */\nexport const SafetyEvidenceJobItemVerifyResultSchema = z.enum(['pending', 'ok', 'mismatch']);\nexport type SafetyEvidenceJobItemVerifyResult = z.infer<typeof SafetyEvidenceJobItemVerifyResultSchema>;\n\n/** `safetyEvidenceJobs/{jobId}/items/{itemId}` — per-object source/destination row.\n * Doc id is the `itemId`. */\nexport const SafetyEvidenceJobItemV1Schema = z.object({\n role: SafetyEvidenceJobItemRoleSchema,\n bucket: z.string().min(1),\n key: z.string().min(1),\n generation: z.string().min(1).optional(),\n sizeBytes: z.number(),\n sha256: z.string().min(1),\n md5: z.string().min(1).optional(),\n verifyResult: SafetyEvidenceJobItemVerifyResultSchema,\n}).strict();\nexport type SafetyEvidenceJobItemV1 = z.infer<typeof SafetyEvidenceJobItemV1Schema>;\n\n/** §A4 disposition method (per evidence location). */\nexport const SafetyEvidenceDispositionMethodSchema = z.enum(['delete', 'cryptoErase']);\nexport type SafetyEvidenceDispositionMethod = z.infer<typeof SafetyEvidenceDispositionMethodSchema>;\n\n/** §A4 disposition result (per evidence location). */\nexport const SafetyEvidenceDispositionResultSchema = z.enum(['gone', 'leftover']);\nexport type SafetyEvidenceDispositionResult = z.infer<typeof SafetyEvidenceDispositionResultSchema>;\n\n/** `safetyEvidenceJobs/{jobId}/disposition/{locationId}` — per-evidence-location\n * deletion-verification record. Doc id is the `locationId`.\n *\n * [M-5] This IS the durable hard-deletion attestation body: the disposition worker runs only after\n * the case reaches `preservationStatus:'dispositionPending'` (every hold ref released + a reviewed\n * disposition job), and records `method` + `verifiedAt` + `result`. Because soft-delete is DISABLED\n * on the evidence bucket, `result:'gone'` attests a verified TRUE hard-deletion (there is no\n * soft-delete/lifecycle tombstone to model — no `softDeletedAt`/`hardDeleteTime`). `generation`\n * pins the exact object generation that was destroyed, so a later object re-created at the same\n * bucket/key (a new generation) is never falsely attested as this destruction. */\nexport const SafetyEvidenceDispositionV1Schema = z.object({\n bucket: z.string().min(1),\n key: z.string().min(1),\n // [M-5] the exact object generation this record attests destroyed — pins the attestation to a\n // single immutable object version so a same-key re-upload (new generation) is not covered by it.\n // Optional: an object with no generation concept (or a leftover with none read) omits it.\n generation: z.string().min(1).optional(),\n method: SafetyEvidenceDispositionMethodSchema,\n verifiedAt: z.number(),\n result: SafetyEvidenceDispositionResultSchema,\n leftoverDetail: z.string().min(1).optional(),\n}).strict();\nexport type SafetyEvidenceDispositionV1 = z.infer<typeof SafetyEvidenceDispositionV1Schema>;\n"]}
|
|
@@ -188,7 +188,7 @@ export type ReportDisposition = z.infer<typeof ReportDispositionSchema>;
|
|
|
188
188
|
/** Reason codes for the privileged setReportDisposition command (§A9). The first five are the
|
|
189
189
|
* not-required / exception reasons (no NCMEC report ever arose, or a triggering signal was
|
|
190
190
|
* corrected); the last two are the report-required reasons (a report IS legally required). The
|
|
191
|
-
* disposition↔reason pairing is enforced by the ONE cross-field rule below (
|
|
191
|
+
* disposition↔reason pairing is enforced by the ONE cross-field rule below (ARCH-102). */
|
|
192
192
|
export declare const ReportDispositionReasonCodeSchema: z.ZodEnum<{
|
|
193
193
|
outOfScopeNotCsea: "outOfScopeNotCsea";
|
|
194
194
|
basisInvalidatedFalseMatch: "basisInvalidatedFalseMatch";
|
|
@@ -205,7 +205,7 @@ export declare const REPORT_REQUIRED_DISPOSITION_REASON_CODES: readonly ["appare
|
|
|
205
205
|
/** The not-required / exception reason codes — legal with every disposition that does NOT assert a
|
|
206
206
|
* reporting obligation ('notRequired', 'correctedNoApparentViolation'). Compile-linked subset. */
|
|
207
207
|
export declare const NOT_REQUIRED_DISPOSITION_REASON_CODES: readonly ["outOfScopeNotCsea", "basisInvalidatedFalseMatch", "duplicateOfFiledReport", "leDirectedNoReport", "nonReportableSafetyConfirmed"];
|
|
208
|
-
/** The ONE cross-field pairing (§A9,
|
|
208
|
+
/** The ONE cross-field pairing (§A9, ARCH-102): which reason codes each disposition permits.
|
|
209
209
|
* Declared HERE once; both the setReportDisposition input (case.ts) and the SafetyDispositionAction
|
|
210
210
|
* console command (admin.ts) apply `refineReportDispositionReasonCode` derived from this map rather
|
|
211
211
|
* than re-declaring the pairing. 'undetermined' is the initial state, never an operator-settable
|
|
@@ -222,7 +222,7 @@ export declare function refineReportDispositionReasonCode(value: {
|
|
|
222
222
|
/** Shared cross-field rule (§A9): disposition 'reportRequired' MUST carry at least one evidence ref —
|
|
223
223
|
* a reporting obligation can only be asserted once the evidence has been revealed. Every OTHER
|
|
224
224
|
* disposition ('notRequired', 'correctedNoApparentViolation', 'undetermined') MAY leave evidenceRefs
|
|
225
|
-
* empty. Declared HERE once (
|
|
225
|
+
* empty. Declared HERE once (ARCH-102) and applied — alongside refineReportDispositionReasonCode — by
|
|
226
226
|
* BOTH the setReportDisposition input schemas (case.ts) and the SafetyStagedAction console command
|
|
227
227
|
* (admin.ts), never re-declared. Reports the failure on the `evidenceRefs` path. */
|
|
228
228
|
export declare function refineReportDispositionEvidenceRefs(value: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foundation.d.ts","sourceRoot":"","sources":["../../../src/doc-schemas/safety/foundation.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB;gFACgF;AAChF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;EAa7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB,0EAGO,CAAC;AAE7C,gEAAgE;AAChE,eAAO,MAAM,mBAAmB;;;EAA0C,CAAC;AAC3E,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;qEAEqE;AACrE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;EA2BnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E;;;oFAGoF;AACpF,eAAO,MAAM,sBAAsB,yDAGe,CAAC;AAEnD;mFACmF;AACnF,eAAO,MAAM,+BAA+B,iOAaM,CAAC;AACnD,MAAM,MAAM,0BAA0B,GAAG,CAAC,OAAO,+BAA+B,CAAC,CAAC,MAAM,CAAC,CAAC;AAO1F;wEACwE;AACxE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BA2BhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,kFAAkF;AAClF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;EAsBlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,mFAAmF;AACnF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;kBAI9B,CAAC;AACZ,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAMlF;mFACmF;AACnF,eAAO,MAAM,uBAAuB;;;;;EAKlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;
|
|
1
|
+
{"version":3,"file":"foundation.d.ts","sourceRoot":"","sources":["../../../src/doc-schemas/safety/foundation.ts"],"names":[],"mappings":"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"}
|
|
@@ -173,7 +173,7 @@ export const ReportDispositionSchema = z.enum([
|
|
|
173
173
|
/** Reason codes for the privileged setReportDisposition command (§A9). The first five are the
|
|
174
174
|
* not-required / exception reasons (no NCMEC report ever arose, or a triggering signal was
|
|
175
175
|
* corrected); the last two are the report-required reasons (a report IS legally required). The
|
|
176
|
-
* disposition↔reason pairing is enforced by the ONE cross-field rule below (
|
|
176
|
+
* disposition↔reason pairing is enforced by the ONE cross-field rule below (ARCH-102). */
|
|
177
177
|
export const ReportDispositionReasonCodeSchema = z.enum([
|
|
178
178
|
'outOfScopeNotCsea',
|
|
179
179
|
'basisInvalidatedFalseMatch',
|
|
@@ -199,7 +199,7 @@ export const NOT_REQUIRED_DISPOSITION_REASON_CODES = [
|
|
|
199
199
|
'leDirectedNoReport',
|
|
200
200
|
'nonReportableSafetyConfirmed',
|
|
201
201
|
];
|
|
202
|
-
/** The ONE cross-field pairing (§A9,
|
|
202
|
+
/** The ONE cross-field pairing (§A9, ARCH-102): which reason codes each disposition permits.
|
|
203
203
|
* Declared HERE once; both the setReportDisposition input (case.ts) and the SafetyDispositionAction
|
|
204
204
|
* console command (admin.ts) apply `refineReportDispositionReasonCode` derived from this map rather
|
|
205
205
|
* than re-declaring the pairing. 'undetermined' is the initial state, never an operator-settable
|
|
@@ -226,7 +226,7 @@ export function refineReportDispositionReasonCode(value, ctx) {
|
|
|
226
226
|
/** Shared cross-field rule (§A9): disposition 'reportRequired' MUST carry at least one evidence ref —
|
|
227
227
|
* a reporting obligation can only be asserted once the evidence has been revealed. Every OTHER
|
|
228
228
|
* disposition ('notRequired', 'correctedNoApparentViolation', 'undetermined') MAY leave evidenceRefs
|
|
229
|
-
* empty. Declared HERE once (
|
|
229
|
+
* empty. Declared HERE once (ARCH-102) and applied — alongside refineReportDispositionReasonCode — by
|
|
230
230
|
* BOTH the setReportDisposition input schemas (case.ts) and the SafetyStagedAction console command
|
|
231
231
|
* (admin.ts), never re-declared. Reports the failure on the `evidenceRefs` path. */
|
|
232
232
|
export function refineReportDispositionEvidenceRefs(value, ctx) {
|