@ttt-productions/ttt-core 0.78.23 → 0.78.25
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/app-mode.d.ts +1 -0
- package/dist/constants/app-mode.d.ts.map +1 -1
- package/dist/constants/app-mode.js +11 -0
- package/dist/constants/app-mode.js.map +1 -1
- package/dist/constants/business-user.d.ts +1 -1
- package/dist/constants/business-user.js +1 -1
- package/dist/constants/business-user.js.map +1 -1
- package/dist/constants/release-flags.d.ts +2 -2
- package/dist/constants/release-flags.d.ts.map +1 -1
- package/dist/constants/release-flags.js +2 -2
- package/dist/constants/release-flags.js.map +1 -1
- package/dist/doc-schemas/chat-sync.d.ts.map +1 -1
- package/dist/doc-schemas/chat-sync.js +3 -2
- package/dist/doc-schemas/chat-sync.js.map +1 -1
- package/dist/doc-schemas/commissions.d.ts +14 -11
- package/dist/doc-schemas/commissions.d.ts.map +1 -1
- package/dist/doc-schemas/commissions.js +14 -4
- package/dist/doc-schemas/commissions.js.map +1 -1
- package/dist/doc-schemas/media-activation-jobs.d.ts.map +1 -1
- package/dist/doc-schemas/media-activation-jobs.js +4 -3
- package/dist/doc-schemas/media-activation-jobs.js.map +1 -1
- package/dist/doc-schemas/media-assets.d.ts +2 -2
- package/dist/doc-schemas/media-assets.d.ts.map +1 -1
- package/dist/doc-schemas/media-assets.js +5 -4
- package/dist/doc-schemas/media-assets.js.map +1 -1
- package/dist/doc-schemas/messaging.d.ts.map +1 -1
- package/dist/doc-schemas/messaging.js +3 -2
- package/dist/doc-schemas/messaging.js.map +1 -1
- package/dist/doc-schemas/ncii/allegations.js +3 -3
- package/dist/doc-schemas/ncii/allegations.js.map +1 -1
- package/dist/doc-schemas/ncii/cases.d.ts.map +1 -1
- package/dist/doc-schemas/ncii/cases.js +4 -3
- package/dist/doc-schemas/ncii/cases.js.map +1 -1
- package/dist/doc-schemas/ncii/config.d.ts.map +1 -1
- package/dist/doc-schemas/ncii/config.js +4 -3
- package/dist/doc-schemas/ncii/config.js.map +1 -1
- package/dist/doc-schemas/ncii/holds.js +3 -3
- package/dist/doc-schemas/ncii/holds.js.map +1 -1
- package/dist/doc-schemas/ncii/removal.js +3 -3
- package/dist/doc-schemas/ncii/removal.js.map +1 -1
- package/dist/doc-schemas/ncii/requests.d.ts.map +1 -1
- package/dist/doc-schemas/ncii/requests.js +4 -3
- package/dist/doc-schemas/ncii/requests.js.map +1 -1
- package/dist/doc-schemas/notification-ledger.d.ts.map +1 -1
- package/dist/doc-schemas/notification-ledger.js +3 -1
- package/dist/doc-schemas/notification-ledger.js.map +1 -1
- package/dist/doc-schemas/payments.d.ts.map +1 -1
- package/dist/doc-schemas/payments.js +2 -1
- package/dist/doc-schemas/payments.js.map +1 -1
- package/dist/doc-schemas/registry.d.ts +108 -35
- package/dist/doc-schemas/registry.d.ts.map +1 -1
- package/dist/doc-schemas/registry.js +4 -0
- package/dist/doc-schemas/registry.js.map +1 -1
- package/dist/doc-schemas/safety/age.d.ts.map +1 -1
- package/dist/doc-schemas/safety/age.js +4 -3
- package/dist/doc-schemas/safety/age.js.map +1 -1
- package/dist/doc-schemas/safety/case-aliases.d.ts.map +1 -1
- package/dist/doc-schemas/safety/case-aliases.js +5 -4
- package/dist/doc-schemas/safety/case-aliases.js.map +1 -1
- package/dist/doc-schemas/safety/case.d.ts.map +1 -1
- package/dist/doc-schemas/safety/case.js +4 -3
- package/dist/doc-schemas/safety/case.js.map +1 -1
- package/dist/doc-schemas/safety/evidence.js +3 -3
- package/dist/doc-schemas/safety/evidence.js.map +1 -1
- package/dist/doc-schemas/safety/foundation.d.ts.map +1 -1
- package/dist/doc-schemas/safety/foundation.js +5 -3
- package/dist/doc-schemas/safety/foundation.js.map +1 -1
- package/dist/doc-schemas/safety/holds.d.ts.map +1 -1
- package/dist/doc-schemas/safety/holds.js +4 -3
- package/dist/doc-schemas/safety/holds.js.map +1 -1
- package/dist/doc-schemas/safety/monitors.d.ts.map +1 -1
- package/dist/doc-schemas/safety/monitors.js +5 -3
- package/dist/doc-schemas/safety/monitors.js.map +1 -1
- package/dist/doc-schemas/safety/provenance.js +3 -3
- package/dist/doc-schemas/safety/provenance.js.map +1 -1
- package/dist/doc-schemas/safety/report.d.ts.map +1 -1
- package/dist/doc-schemas/safety/report.js +4 -3
- package/dist/doc-schemas/safety/report.js.map +1 -1
- package/dist/doc-schemas/safety/sagas.js +3 -3
- package/dist/doc-schemas/safety/sagas.js.map +1 -1
- package/dist/doc-schemas/social.d.ts +130 -0
- package/dist/doc-schemas/social.d.ts.map +1 -1
- package/dist/doc-schemas/social.js +91 -2
- package/dist/doc-schemas/social.js.map +1 -1
- package/dist/doc-schemas/square-announcement-jobs.d.ts +306 -14
- package/dist/doc-schemas/square-announcement-jobs.d.ts.map +1 -1
- package/dist/doc-schemas/square-announcement-jobs.js +15 -2
- package/dist/doc-schemas/square-announcement-jobs.js.map +1 -1
- package/dist/doc-schemas/user.js +3 -3
- package/dist/doc-schemas/user.js.map +1 -1
- package/dist/doc-schemas/work-project.js +2 -2
- package/dist/doc-schemas/work-project.js.map +1 -1
- package/dist/ids/chat-ids.d.ts +3 -2
- package/dist/ids/chat-ids.d.ts.map +1 -1
- package/dist/ids/chat-ids.js +3 -2
- package/dist/ids/chat-ids.js.map +1 -1
- package/dist/media/domain-events-admin.d.ts +0 -7
- package/dist/media/domain-events-admin.d.ts.map +1 -1
- package/dist/media/domain-events-admin.js +0 -11
- package/dist/media/domain-events-admin.js.map +1 -1
- package/dist/media/domain-events.d.ts +0 -6
- package/dist/media/domain-events.d.ts.map +1 -1
- package/dist/media/domain-events.js +1 -2
- package/dist/media/domain-events.js.map +1 -1
- package/dist/media/hall-library-target-fields.js +1 -1
- package/dist/media/hall-library-target-fields.js.map +1 -1
- package/dist/media/pending-media.d.ts +0 -54
- package/dist/media/pending-media.d.ts.map +1 -1
- package/dist/media/photodna-coverage.d.ts.map +1 -1
- package/dist/media/photodna-coverage.js +5 -3
- package/dist/media/photodna-coverage.js.map +1 -1
- package/dist/paths/related-ids.js +1 -1
- package/dist/paths/related-ids.js.map +1 -1
- package/dist/safety/ncii-intake-derivations.d.ts.map +1 -1
- package/dist/safety/ncii-intake-derivations.js +4 -2
- package/dist/safety/ncii-intake-derivations.js.map +1 -1
- package/dist/safety/resource-keys.d.ts.map +1 -1
- package/dist/safety/resource-keys.js +2 -1
- package/dist/safety/resource-keys.js.map +1 -1
- package/dist/schemas/chat.js +3 -3
- package/dist/schemas/chat.js.map +1 -1
- package/dist/schemas/ncii.js +1 -1
- package/dist/schemas/ncii.js.map +1 -1
- package/dist/schemas/notification.d.ts +8 -8
- package/dist/schemas/notification.d.ts.map +1 -1
- package/dist/schemas/notification.js +17 -11
- package/dist/schemas/notification.js.map +1 -1
- package/dist/types/social.d.ts +1 -45
- package/dist/types/social.d.ts.map +1 -1
- package/dist/types/social.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sagas.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/sagas.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — three independent durable sagas + the closure coordinator\n// (Appendix A §A5, Finding-H5 / Finding-H6).\n//\n// Quarantine, NCMEC reporting, and account action are THREE independent durable\n// sagas. The quarantine job NEVER folds reporting or account action into its\n// phases — it can be `quarantineComplete` while the other two are still open, so\n// no doc ever lies about quarantine completion. Each saga is idempotent by\n// `commandId`; the reconciler verifies external state, never a prior response.\n//\n// Every shape here is transcribed verbatim from docs/code_changes_needed/\n// trust-and-safety/IMPLEMENTATION_PLAN.md Appendix A §A5 — no invented values, no\n// placeholders.\n//\n// SHARED enums come from ./foundation.js (the single source for every\n// cross-cluster enum); they are NEVER redefined here. This cluster IMPORTS\n// NcmecSubmissionStateSchema (the §A9 reporting lifecycle) from foundation.\n//\n// Collection note: this cluster introduces THREE NEW Firestore collections plus\n// one overflow subcollection under `quarantineSagaJobs`. Wiring collections.ts /\n// path-builders.ts / registry.ts is deferred to the app leg (the orchestrator\n// binds the schemas + path builders there); the composite doc-id shapes are\n// documented on each schema below.\n//\n// CLOSURE COORDINATOR — there is NO doc for it. The case is \"operationally\n// resolvable\" via a PROJECTION computed on the case root from the three\n// independent statuses (see the closure predicate comment at the bottom of this\n// file). Do NOT create a closure-coordinator document.\n\nimport { z } from 'zod';\nimport { NcmecSubmissionStateSchema } from './foundation.js';\n\n// ===========================================================================\n// A5 — quarantineSagaJobs/{caseId}\n// Quarantine ONLY (hold → serving-deny → evidence → active-byte removal). Never\n// folds reporting / account action. Doc id is the `caseId`.\n// ===========================================================================\n\n/** Top-level run status of the quarantine saga. */\nexport const QuarantineStatusSchema = z.enum([\n 'running',\n 'quarantineComplete',\n 'deadLetter',\n]);\nexport type QuarantineStatus = z.infer<typeof QuarantineStatusSchema>;\n\n/** The FULL quarantine phase enum. `servingDeny*` precede `evidenceCopying`;\n * `activeCopiesRemoval*` require `evidenceVerified`. */\nexport const QuarantinePhaseSchema = z.enum([\n 'holdCommitted',\n 'sourceManifestCaptured',\n 'servingDenyRequested',\n 'servingDenyVerified',\n 'evidenceCopying',\n 'evidenceVerified',\n 'activeCopiesRemovalRequested',\n 'activeCopiesRemovalVerified',\n 'quarantineComplete',\n]);\nexport type QuarantinePhase = z.infer<typeof QuarantinePhaseSchema>;\n\n/** `quarantineSagaJobs/{caseId}` — quarantine-only durable saga. Doc id is the\n * `caseId`. `commandId` is deterministic per `(caseId, phase)`. `relatedAssetIds`\n * is bounded at MAX 256; overflow → `…/relatedAssets/{assetId}`. */\nexport const QuarantineSagaJobV1Schema = z.object({\n schemaVersion: z.literal(1),\n caseId: z.string().min(1),\n quarantineStatus: QuarantineStatusSchema,\n phase: QuarantinePhaseSchema,\n phaseVersion: z.number(),\n commandId: z.string().min(1), // deterministic per (caseId, phase)\n relatedAssetIds: z.array(z.string().min(1)).max(256), // bounded; overflow → …/relatedAssets/{assetId}\n attemptCount: z.number(),\n nextAttemptAt: z.number(),\n leaseOwner: z.string().min(1).optional(),\n leaseExpiresAt: z.number().optional(),\n lastError: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n completedAt: z.number().optional(),\n}).strict();\nexport type QuarantineSagaJobV1 = z.infer<typeof QuarantineSagaJobV1Schema>;\n\n/** `quarantineSagaJobs/{caseId}/relatedAssets/{assetId}` — overflow beyond\n * `relatedAssetIds` MAX 256. Doc id is the `assetId`. */\nexport const QuarantineSagaRelatedAssetV1Schema = z.object({\n rootIngestId: z.string().min(1),\n addedAt: z.number(),\n}).strict();\nexport type QuarantineSagaRelatedAssetV1 = z.infer<typeof QuarantineSagaRelatedAssetV1Schema>;\n\n// ===========================================================================\n// A5 — ncmecSubmissionJobs/{caseId}__{submissionId}\n// The API/manual reporting lifecycle. Drives the …/ncmecSubmissions/{submissionId}\n// records + …/attempts; owns retries, ambiguity reconciliation, manual-portal\n// fallback, supplemental/correction. Doc id is the deterministic composite\n// `{caseId}__{submissionId}`.\n// ===========================================================================\n\n/** `ncmecSubmissionJobs/{caseId}__{submissionId}` — reporting-lifecycle durable\n * saga. Doc id is the deterministic composite `{caseId}__{submissionId}`.\n * `commandId` is the saga's idempotency key. `state` is the §A9\n * NcmecSubmissionState (NO `notRequired` — that lives on ReportDisposition). */\nexport const NcmecSubmissionJobV1Schema = z.object({\n schemaVersion: z.literal(1),\n caseId: z.string().min(1),\n submissionId: z.string().min(1),\n state: NcmecSubmissionStateSchema, // §A9 NcmecSubmissionState\n commandId: z.string().min(1),\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(),\n}).strict();\nexport type NcmecSubmissionJobV1 = z.infer<typeof NcmecSubmissionJobV1Schema>;\n\n// ===========================================================================\n// A5 — accountActionCommands/{caseId}__{uid}\n// The per-account safety-action lifecycle. Doc id is the deterministic composite\n// `{caseId}__{uid}`. A dead-letter replay never re-issues a second ban\n// (idempotent `commandId` + merge-generation check).\n// ===========================================================================\n\n/** The per-account safety action this command applies. `reinstate` is the inverse of a\n * restriction: it restores `status:'active'`, clears `privateData.safetyLocked`, and\n * re-enables a disabled Auth account (used to lift a safety-lock / ban when a case is\n * closed as a false positive). The case's safety HOLDS are released separately by the\n * case-close path, not by this action. */\nexport const AccountActionSchema = z.enum([\n 'ban',\n 'suspend',\n 'watch',\n 'safetyLocked',\n 'reinstate',\n 'none',\n]);\nexport type AccountAction = z.infer<typeof AccountActionSchema>;\n\n/** Where the action originated. */\nexport const AccountActionSourceSchema = z.enum(['autoHash', 'operator']);\nexport type AccountActionSource = z.infer<typeof AccountActionSourceSchema>;\n\n/** Command lifecycle status. `deadLetter` parks a command whose attempt budget is\n * exhausted (the drain query stops matching it); an operator replays it via\n * `adminReplayDeadLetter` (generic reset to `pending`). */\nexport const AccountActionStatusSchema = z.enum(['pending', 'applied', 'reverted', 'deadLetter']);\nexport type AccountActionStatus = z.infer<typeof AccountActionStatusSchema>;\n\n/** `accountActionCommands/{caseId}__{uid}` — per-account safety-action durable\n * saga. Doc id is the deterministic composite `{caseId}__{uid}`. `commandId` is\n * the saga's idempotency key. */\nexport const AccountActionCommandV1Schema = z.object({\n schemaVersion: z.literal(1),\n caseId: z.string().min(1),\n targetUid: z.string().min(1),\n action: AccountActionSchema,\n source: AccountActionSourceSchema,\n status: AccountActionStatusSchema,\n commandId: z.string().min(1),\n attemptCount: z.number(),\n nextAttemptAt: z.number(),\n leaseOwner: z.string().min(1).optional(),\n leaseExpiresAt: z.number().optional(),\n lastError: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n completedAt: z.number().optional(),\n}).strict();\nexport type AccountActionCommandV1 = z.infer<typeof AccountActionCommandV1Schema>;\n\n// ===========================================================================\n// A5 — CLOSURE COORDINATOR (a PROJECTION on the case root, NOT a doc).\n//\n// There is NO closure-coordinator document. The case is OPERATIONALLY RESOLVABLE\n// only when ALL THREE independent statuses agree:\n//\n// 1. quarantine : QuarantineSagaJobV1.quarantineStatus === 'quarantineComplete'\n// 2. account action : case-root accountActionStatus ∈ { 'noAccountActionRequired', 'resolved' }\n// 3. reporting predicate (Finding-H6):\n// ( case-root reportDisposition === 'notRequired' AND no NCMEC submission was ever opened )\n// OR ( the submission's state === 'completed' )\n//\n// Reporting closure keys on the case-root `reportDisposition` (§A9\n// ReportDisposition), NOT on a `notRequired` submission state (that value no\n// longer exists on NcmecSubmissionState). A `notRequired`-disposed case is never\n// blocked on a non-existent report; a human-review case stays\n// `operatorDecisionPending` until the operator commands the action.\n// ===========================================================================\n"]}
|
|
1
|
+
{"version":3,"file":"sagas.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/sagas.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — three independent durable sagas + the closure coordinator\n// (Appendix A §A5, Finding-H5 / Finding-H6).\n//\n// Quarantine, NCMEC reporting, and account action are THREE independent durable\n// sagas. The quarantine job NEVER folds reporting or account action into its\n// phases — it can be `quarantineComplete` while the other two are still open, so\n// no doc ever lies about quarantine completion. Each saga is idempotent by\n// `commandId`; the reconciler verifies external state, never a prior response.\n//\n// Every shape here is transcribed verbatim from the frozen Trust & Safety spec\n// (Appendix A §A5) — no invented values, no placeholders; the durable design owner\n// is ttt-prod docs/design/csam-detection-and-response.md.\n//\n// SHARED enums come from ./foundation.js (the single source for every\n// cross-cluster enum); they are NEVER redefined here. This cluster IMPORTS\n// NcmecSubmissionStateSchema (the §A9 reporting lifecycle) from foundation.\n//\n// Collection note: this cluster introduces THREE NEW Firestore collections plus\n// one overflow subcollection under `quarantineSagaJobs`. Wiring collections.ts /\n// path-builders.ts / registry.ts is deferred to the app leg (the orchestrator\n// binds the schemas + path builders there); the composite doc-id shapes are\n// documented on each schema below.\n//\n// CLOSURE COORDINATOR — there is NO doc for it. The case is \"operationally\n// resolvable\" via a PROJECTION computed on the case root from the three\n// independent statuses (see the closure predicate comment at the bottom of this\n// file). Do NOT create a closure-coordinator document.\n\nimport { z } from 'zod';\nimport { NcmecSubmissionStateSchema } from './foundation.js';\n\n// ===========================================================================\n// A5 — quarantineSagaJobs/{caseId}\n// Quarantine ONLY (hold → serving-deny → evidence → active-byte removal). Never\n// folds reporting / account action. Doc id is the `caseId`.\n// ===========================================================================\n\n/** Top-level run status of the quarantine saga. */\nexport const QuarantineStatusSchema = z.enum([\n 'running',\n 'quarantineComplete',\n 'deadLetter',\n]);\nexport type QuarantineStatus = z.infer<typeof QuarantineStatusSchema>;\n\n/** The FULL quarantine phase enum. `servingDeny*` precede `evidenceCopying`;\n * `activeCopiesRemoval*` require `evidenceVerified`. */\nexport const QuarantinePhaseSchema = z.enum([\n 'holdCommitted',\n 'sourceManifestCaptured',\n 'servingDenyRequested',\n 'servingDenyVerified',\n 'evidenceCopying',\n 'evidenceVerified',\n 'activeCopiesRemovalRequested',\n 'activeCopiesRemovalVerified',\n 'quarantineComplete',\n]);\nexport type QuarantinePhase = z.infer<typeof QuarantinePhaseSchema>;\n\n/** `quarantineSagaJobs/{caseId}` — quarantine-only durable saga. Doc id is the\n * `caseId`. `commandId` is deterministic per `(caseId, phase)`. `relatedAssetIds`\n * is bounded at MAX 256; overflow → `…/relatedAssets/{assetId}`. */\nexport const QuarantineSagaJobV1Schema = z.object({\n schemaVersion: z.literal(1),\n caseId: z.string().min(1),\n quarantineStatus: QuarantineStatusSchema,\n phase: QuarantinePhaseSchema,\n phaseVersion: z.number(),\n commandId: z.string().min(1), // deterministic per (caseId, phase)\n relatedAssetIds: z.array(z.string().min(1)).max(256), // bounded; overflow → …/relatedAssets/{assetId}\n attemptCount: z.number(),\n nextAttemptAt: z.number(),\n leaseOwner: z.string().min(1).optional(),\n leaseExpiresAt: z.number().optional(),\n lastError: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n completedAt: z.number().optional(),\n}).strict();\nexport type QuarantineSagaJobV1 = z.infer<typeof QuarantineSagaJobV1Schema>;\n\n/** `quarantineSagaJobs/{caseId}/relatedAssets/{assetId}` — overflow beyond\n * `relatedAssetIds` MAX 256. Doc id is the `assetId`. */\nexport const QuarantineSagaRelatedAssetV1Schema = z.object({\n rootIngestId: z.string().min(1),\n addedAt: z.number(),\n}).strict();\nexport type QuarantineSagaRelatedAssetV1 = z.infer<typeof QuarantineSagaRelatedAssetV1Schema>;\n\n// ===========================================================================\n// A5 — ncmecSubmissionJobs/{caseId}__{submissionId}\n// The API/manual reporting lifecycle. Drives the …/ncmecSubmissions/{submissionId}\n// records + …/attempts; owns retries, ambiguity reconciliation, manual-portal\n// fallback, supplemental/correction. Doc id is the deterministic composite\n// `{caseId}__{submissionId}`.\n// ===========================================================================\n\n/** `ncmecSubmissionJobs/{caseId}__{submissionId}` — reporting-lifecycle durable\n * saga. Doc id is the deterministic composite `{caseId}__{submissionId}`.\n * `commandId` is the saga's idempotency key. `state` is the §A9\n * NcmecSubmissionState (NO `notRequired` — that lives on ReportDisposition). */\nexport const NcmecSubmissionJobV1Schema = z.object({\n schemaVersion: z.literal(1),\n caseId: z.string().min(1),\n submissionId: z.string().min(1),\n state: NcmecSubmissionStateSchema, // §A9 NcmecSubmissionState\n commandId: z.string().min(1),\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(),\n}).strict();\nexport type NcmecSubmissionJobV1 = z.infer<typeof NcmecSubmissionJobV1Schema>;\n\n// ===========================================================================\n// A5 — accountActionCommands/{caseId}__{uid}\n// The per-account safety-action lifecycle. Doc id is the deterministic composite\n// `{caseId}__{uid}`. A dead-letter replay never re-issues a second ban\n// (idempotent `commandId` + merge-generation check).\n// ===========================================================================\n\n/** The per-account safety action this command applies. `reinstate` is the inverse of a\n * restriction: it restores `status:'active'`, clears `privateData.safetyLocked`, and\n * re-enables a disabled Auth account (used to lift a safety-lock / ban when a case is\n * closed as a false positive). The case's safety HOLDS are released separately by the\n * case-close path, not by this action. */\nexport const AccountActionSchema = z.enum([\n 'ban',\n 'suspend',\n 'watch',\n 'safetyLocked',\n 'reinstate',\n 'none',\n]);\nexport type AccountAction = z.infer<typeof AccountActionSchema>;\n\n/** Where the action originated. */\nexport const AccountActionSourceSchema = z.enum(['autoHash', 'operator']);\nexport type AccountActionSource = z.infer<typeof AccountActionSourceSchema>;\n\n/** Command lifecycle status. `deadLetter` parks a command whose attempt budget is\n * exhausted (the drain query stops matching it); an operator replays it via\n * `adminReplayDeadLetter` (generic reset to `pending`). */\nexport const AccountActionStatusSchema = z.enum(['pending', 'applied', 'reverted', 'deadLetter']);\nexport type AccountActionStatus = z.infer<typeof AccountActionStatusSchema>;\n\n/** `accountActionCommands/{caseId}__{uid}` — per-account safety-action durable\n * saga. Doc id is the deterministic composite `{caseId}__{uid}`. `commandId` is\n * the saga's idempotency key. */\nexport const AccountActionCommandV1Schema = z.object({\n schemaVersion: z.literal(1),\n caseId: z.string().min(1),\n targetUid: z.string().min(1),\n action: AccountActionSchema,\n source: AccountActionSourceSchema,\n status: AccountActionStatusSchema,\n commandId: z.string().min(1),\n attemptCount: z.number(),\n nextAttemptAt: z.number(),\n leaseOwner: z.string().min(1).optional(),\n leaseExpiresAt: z.number().optional(),\n lastError: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n completedAt: z.number().optional(),\n}).strict();\nexport type AccountActionCommandV1 = z.infer<typeof AccountActionCommandV1Schema>;\n\n// ===========================================================================\n// A5 — CLOSURE COORDINATOR (a PROJECTION on the case root, NOT a doc).\n//\n// There is NO closure-coordinator document. The case is OPERATIONALLY RESOLVABLE\n// only when ALL THREE independent statuses agree:\n//\n// 1. quarantine : QuarantineSagaJobV1.quarantineStatus === 'quarantineComplete'\n// 2. account action : case-root accountActionStatus ∈ { 'noAccountActionRequired', 'resolved' }\n// 3. reporting predicate (Finding-H6):\n// ( case-root reportDisposition === 'notRequired' AND no NCMEC submission was ever opened )\n// OR ( the submission's state === 'completed' )\n//\n// Reporting closure keys on the case-root `reportDisposition` (§A9\n// ReportDisposition), NOT on a `notRequired` submission state (that value no\n// longer exists on NcmecSubmissionState). A `notRequired`-disposed case is never\n// blocked on a non-existent report; a human-review case stays\n// `operatorDecisionPending` until the operator commands the action.\n// ===========================================================================\n"]}
|
|
@@ -31,6 +31,23 @@ export declare const SquareStreetzPostTypeSchema: z.ZodEnum<{
|
|
|
31
31
|
NEW_COMMISSION: "NEW_COMMISSION";
|
|
32
32
|
}>;
|
|
33
33
|
export type SquareStreetzPostType = z.infer<typeof SquareStreetzPostTypeSchema>;
|
|
34
|
+
/**
|
|
35
|
+
* squareStreetzFeed/activePosts/socialPosts/{postId}.
|
|
36
|
+
*
|
|
37
|
+
* **Media-pair invariant (MEDIA-101) — enforced by the superRefine below:**
|
|
38
|
+
* `mediaAssetId` and `mediaType` are ONE unit — both present, or both absent.
|
|
39
|
+
* Gateway URLs are extensionless, so nothing downstream can recover the kind from
|
|
40
|
+
* the id: a post persisted with an asset and NO kind classifies as `'other'` and
|
|
41
|
+
* `AppMediaPreview` renders a Download link INSTEAD of the image/video. The mirror
|
|
42
|
+
* case (a kind with no asset) is an orphan that describes media the post does not
|
|
43
|
+
* carry. Declared HERE, on the canonical doc schema (ARCH-102), so every writer
|
|
44
|
+
* inherits it from the one post-create chokepoint's parse rather than each write
|
|
45
|
+
* site re-deciding — and so no reader ever needs a `?? 'other'` guess.
|
|
46
|
+
*
|
|
47
|
+
* Announcement posts REFERENCE a source asset (audition `videoAssetId`, commission
|
|
48
|
+
* `commissionAttachment.mediaAssetId`), so the kind always comes from that source —
|
|
49
|
+
* it is never invented or defaulted at the post write.
|
|
50
|
+
*/
|
|
34
51
|
export declare const SquareStreetzPostSchema: z.ZodObject<{
|
|
35
52
|
postId: z.ZodString;
|
|
36
53
|
createdBy: z.ZodObject<{
|
|
@@ -75,6 +92,119 @@ export declare const SquareStreetzPostSchema: z.ZodObject<{
|
|
|
75
92
|
hidden: z.ZodBoolean;
|
|
76
93
|
}, z.core.$strip>;
|
|
77
94
|
export type SquareStreetzPost = z.infer<typeof SquareStreetzPostSchema>;
|
|
95
|
+
/**
|
|
96
|
+
* The create/announcement transport payload for a SquareStreetz post — the exact input
|
|
97
|
+
* `runManageSquareStreetzPost` accepts. Every enqueue site (the durable
|
|
98
|
+
* `squareAnnouncementJobs` outbox) and the manual post callables build one of these; the
|
|
99
|
+
* different post types populate different subsets, so every field beyond `userId` is
|
|
100
|
+
* optional. The TYPE is inferred from this schema (ARCH-102 — one declaration; the
|
|
101
|
+
* frontend extends it with a local `mediaFile?: File`).
|
|
102
|
+
*
|
|
103
|
+
* NON-strict and carrying NO cross-field pairing refinement ON PURPOSE: it is parsed at
|
|
104
|
+
* ENQUEUE inside the announcing transaction (ttt-prod square-announcement-outbox.ts), so a
|
|
105
|
+
* throw here would fail the user's primary action over an announcement defect (ENG-009). It
|
|
106
|
+
* validates that each present field has its canonical type and strips unknowns; the
|
|
107
|
+
* `mediaAssetId`↔`mediaType` pairing (MEDIA-101) is enforced at DELIVERY, where the post
|
|
108
|
+
* core parses `SquareStreetzPostSchema` and a failure dead-letters the job instead.
|
|
109
|
+
*/
|
|
110
|
+
export declare const SquareStreetzPostPayloadSchema: z.ZodObject<{
|
|
111
|
+
userId: z.ZodString;
|
|
112
|
+
mentions: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
113
|
+
placeholder: z.ZodString;
|
|
114
|
+
type: z.ZodEnum<{
|
|
115
|
+
workRealm: "workRealm";
|
|
116
|
+
workProject: "workProject";
|
|
117
|
+
audition: "audition";
|
|
118
|
+
user: "user";
|
|
119
|
+
commission: "commission";
|
|
120
|
+
}>;
|
|
121
|
+
id: z.ZodString;
|
|
122
|
+
}, z.core.$strict>>>;
|
|
123
|
+
newMediaAssetId: z.ZodOptional<z.ZodString>;
|
|
124
|
+
craftSkill: z.ZodOptional<z.ZodObject<{
|
|
125
|
+
id: z.ZodString;
|
|
126
|
+
name: z.ZodString;
|
|
127
|
+
mediaAssetId: z.ZodString;
|
|
128
|
+
type: z.ZodEnum<{
|
|
129
|
+
video: "video";
|
|
130
|
+
image: "image";
|
|
131
|
+
audio: "audio";
|
|
132
|
+
}>;
|
|
133
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
134
|
+
acting: "acting";
|
|
135
|
+
"voice-over": "voice-over";
|
|
136
|
+
singing: "singing";
|
|
137
|
+
rapping: "rapping";
|
|
138
|
+
"instrumental-performance": "instrumental-performance";
|
|
139
|
+
"dance-choreography": "dance-choreography";
|
|
140
|
+
"stand-up-sketch-comedy": "stand-up-sketch-comedy";
|
|
141
|
+
"writing-storytelling": "writing-storytelling";
|
|
142
|
+
songwriting: "songwriting";
|
|
143
|
+
"poetry-spoken-word": "poetry-spoken-word";
|
|
144
|
+
"drawing-illustration": "drawing-illustration";
|
|
145
|
+
painting: "painting";
|
|
146
|
+
animation: "animation";
|
|
147
|
+
"graphic-design": "graphic-design";
|
|
148
|
+
photography: "photography";
|
|
149
|
+
"cinematography-camera": "cinematography-camera";
|
|
150
|
+
"video-editing": "video-editing";
|
|
151
|
+
"visual-effects": "visual-effects";
|
|
152
|
+
directing: "directing";
|
|
153
|
+
"costume-makeup": "costume-makeup";
|
|
154
|
+
"set-prop-design": "set-prop-design";
|
|
155
|
+
"music-production": "music-production";
|
|
156
|
+
"composing-scoring": "composing-scoring";
|
|
157
|
+
"sound-design": "sound-design";
|
|
158
|
+
}>>>;
|
|
159
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
160
|
+
original: "original";
|
|
161
|
+
mimicOnTtt: "mimicOnTtt";
|
|
162
|
+
mimicOffTtt: "mimicOffTtt";
|
|
163
|
+
}>>;
|
|
164
|
+
source: z.ZodOptional<z.ZodObject<{
|
|
165
|
+
type: z.ZodEnum<{
|
|
166
|
+
workProject: "workProject";
|
|
167
|
+
user: "user";
|
|
168
|
+
}>;
|
|
169
|
+
id: z.ZodString;
|
|
170
|
+
}, z.core.$strict>>;
|
|
171
|
+
}, z.core.$strip>>;
|
|
172
|
+
craftSkillId: z.ZodOptional<z.ZodString>;
|
|
173
|
+
workProjectTitle: z.ZodOptional<z.ZodString>;
|
|
174
|
+
workProjectId: z.ZodOptional<z.ZodString>;
|
|
175
|
+
workProjectType: z.ZodOptional<z.ZodEnum<{
|
|
176
|
+
Tales: "Tales";
|
|
177
|
+
Tunes: "Tunes";
|
|
178
|
+
Television: "Television";
|
|
179
|
+
}>>;
|
|
180
|
+
workProjectDescription: z.ZodOptional<z.ZodString>;
|
|
181
|
+
workRealmId: z.ZodOptional<z.ZodString>;
|
|
182
|
+
workRealmTitle: z.ZodOptional<z.ZodString>;
|
|
183
|
+
hallItemId: z.ZodOptional<z.ZodString>;
|
|
184
|
+
hallItemTitle: z.ZodOptional<z.ZodString>;
|
|
185
|
+
hallSubItemType: z.ZodOptional<z.ZodEnum<{
|
|
186
|
+
chapter: "chapter";
|
|
187
|
+
track: "track";
|
|
188
|
+
episode: "episode";
|
|
189
|
+
}>>;
|
|
190
|
+
content: z.ZodOptional<z.ZodString>;
|
|
191
|
+
mediaAssetId: z.ZodOptional<z.ZodString>;
|
|
192
|
+
mediaType: z.ZodOptional<z.ZodEnum<{
|
|
193
|
+
video: "video";
|
|
194
|
+
image: "image";
|
|
195
|
+
audio: "audio";
|
|
196
|
+
other: "other";
|
|
197
|
+
}>>;
|
|
198
|
+
createdAt: z.ZodOptional<z.ZodNumber>;
|
|
199
|
+
auditionId: z.ZodOptional<z.ZodString>;
|
|
200
|
+
commissionListingId: z.ZodOptional<z.ZodString>;
|
|
201
|
+
auditionAnnounceKind: z.ZodOptional<z.ZodEnum<{
|
|
202
|
+
work: "work";
|
|
203
|
+
platform: "platform";
|
|
204
|
+
sponsored: "sponsored";
|
|
205
|
+
}>>;
|
|
206
|
+
}, z.core.$strip>;
|
|
207
|
+
export type SquareStreetzPostPayload = z.infer<typeof SquareStreetzPostPayloadSchema>;
|
|
78
208
|
export declare const MentionHistoryItemSchema: z.ZodObject<{
|
|
79
209
|
placeholder: z.ZodString;
|
|
80
210
|
type: z.ZodEnum<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"social.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/social.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"social.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/social.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB;;+EAE+E;AAC/E,eAAO,MAAM,eAAe;;;;;EAA+C,CAAC;AAC5E,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAGxD;;+EAE+E;AAC/E,eAAO,MAAM,0BAA0B;;;;EAA4C,CAAC;AACpF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,eAAO,MAAM,2BAA2B;;;;;;;;;;;EAWtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsClC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkCzC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAEtF,eAAO,MAAM,wBAAwB;;;;;;;;;;;kBAAiD,CAAC;AACvF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;iBAGvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAQlF,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;iBAK1C,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF,eAAO,MAAM,gBAAgB;;;;;;;;;iBAK3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAK1D,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAKhE,eAAO,MAAM,uBAAuB;;iBAElC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAIxE,eAAO,MAAM,mBAAmB;;;iBAG9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
|
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { MentionSchema } from '../media/atoms.js';
|
|
7
7
|
import { FollowableTargetTypeSchema } from '../schemas/social.js';
|
|
8
|
+
import { ContentMediaKindSchema } from './media-assets.js';
|
|
9
|
+
import { CraftSkillKindSchema, CraftSkillSourceReferenceSchema } from './user.js';
|
|
10
|
+
import { HallSubItemTypeSchema } from './content.js';
|
|
11
|
+
import { CRAFT_SKILL_TAG_VALUES } from '../constants/options.js';
|
|
12
|
+
import { WORK_PROJECT_TYPE_KEYS } from '../types/content.js';
|
|
8
13
|
/** The ONE canonical display/transport media-type family (the 'other' bucket covers
|
|
9
14
|
* non-previewable kinds). Distinct from the 3-value stored ContentMediaKindSchema
|
|
10
15
|
* (doc-schemas/media-assets.ts) and media-schemas' generic MediaKindSchema. */
|
|
@@ -26,6 +31,23 @@ export const SquareStreetzPostTypeSchema = z.enum([
|
|
|
26
31
|
'NEW_AUDITION',
|
|
27
32
|
'NEW_COMMISSION',
|
|
28
33
|
]);
|
|
34
|
+
/**
|
|
35
|
+
* squareStreetzFeed/activePosts/socialPosts/{postId}.
|
|
36
|
+
*
|
|
37
|
+
* **Media-pair invariant (MEDIA-101) — enforced by the superRefine below:**
|
|
38
|
+
* `mediaAssetId` and `mediaType` are ONE unit — both present, or both absent.
|
|
39
|
+
* Gateway URLs are extensionless, so nothing downstream can recover the kind from
|
|
40
|
+
* the id: a post persisted with an asset and NO kind classifies as `'other'` and
|
|
41
|
+
* `AppMediaPreview` renders a Download link INSTEAD of the image/video. The mirror
|
|
42
|
+
* case (a kind with no asset) is an orphan that describes media the post does not
|
|
43
|
+
* carry. Declared HERE, on the canonical doc schema (ARCH-102), so every writer
|
|
44
|
+
* inherits it from the one post-create chokepoint's parse rather than each write
|
|
45
|
+
* site re-deciding — and so no reader ever needs a `?? 'other'` guess.
|
|
46
|
+
*
|
|
47
|
+
* Announcement posts REFERENCE a source asset (audition `videoAssetId`, commission
|
|
48
|
+
* `commissionAttachment.mediaAssetId`), so the kind always comes from that source —
|
|
49
|
+
* it is never invented or defaulted at the post write.
|
|
50
|
+
*/
|
|
29
51
|
export const SquareStreetzPostSchema = z.object({
|
|
30
52
|
postId: z.string(),
|
|
31
53
|
createdBy: z.object({ uid: z.string() }),
|
|
@@ -33,7 +55,9 @@ export const SquareStreetzPostSchema = z.object({
|
|
|
33
55
|
content: z.string(),
|
|
34
56
|
mentions: z.array(MentionSchema).optional(),
|
|
35
57
|
relatedIds: z.array(z.string()),
|
|
58
|
+
/** Paired with `mediaType` — see the media-pair invariant above. */
|
|
36
59
|
mediaAssetId: z.string().optional(),
|
|
60
|
+
/** Paired with `mediaAssetId` — see the media-pair invariant above. */
|
|
37
61
|
mediaType: mediaTypeSchema.optional(),
|
|
38
62
|
createdAt: z.number(),
|
|
39
63
|
likes: z.number(),
|
|
@@ -44,9 +68,74 @@ export const SquareStreetzPostSchema = z.object({
|
|
|
44
68
|
// flag on a post — the legacy pre-finalize upload-gating (`visible`) and automated
|
|
45
69
|
// text-moderation outcome (`moderationStatus`/`moderationReason`/`moderationLayer`)
|
|
46
70
|
// fields were removed 2026-07-03: nothing wrote them (posts are created only AFTER
|
|
47
|
-
// media finalize under pattern C), so they were dead.
|
|
48
|
-
//
|
|
71
|
+
// media finalize under pattern C), so they were dead. Durable owner:
|
|
72
|
+
// ttt-prod docs/design/streetz-social-feed.md.
|
|
49
73
|
hidden: z.boolean(),
|
|
74
|
+
}).superRefine((val, ctx) => {
|
|
75
|
+
if (val.mediaAssetId !== undefined && val.mediaType === undefined) {
|
|
76
|
+
ctx.addIssue({
|
|
77
|
+
code: 'custom',
|
|
78
|
+
path: ['mediaType'],
|
|
79
|
+
message: 'mediaType is required whenever a post carries mediaAssetId (MEDIA-101: an extensionless gateway URL with no kind renders a Download link instead of the media)',
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (val.mediaType !== undefined && val.mediaAssetId === undefined) {
|
|
83
|
+
ctx.addIssue({
|
|
84
|
+
code: 'custom',
|
|
85
|
+
path: ['mediaAssetId'],
|
|
86
|
+
message: 'mediaType is only allowed on a post that carries mediaAssetId — an orphan kind describes media the post does not have',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
/**
|
|
91
|
+
* The create/announcement transport payload for a SquareStreetz post — the exact input
|
|
92
|
+
* `runManageSquareStreetzPost` accepts. Every enqueue site (the durable
|
|
93
|
+
* `squareAnnouncementJobs` outbox) and the manual post callables build one of these; the
|
|
94
|
+
* different post types populate different subsets, so every field beyond `userId` is
|
|
95
|
+
* optional. The TYPE is inferred from this schema (ARCH-102 — one declaration; the
|
|
96
|
+
* frontend extends it with a local `mediaFile?: File`).
|
|
97
|
+
*
|
|
98
|
+
* NON-strict and carrying NO cross-field pairing refinement ON PURPOSE: it is parsed at
|
|
99
|
+
* ENQUEUE inside the announcing transaction (ttt-prod square-announcement-outbox.ts), so a
|
|
100
|
+
* throw here would fail the user's primary action over an announcement defect (ENG-009). It
|
|
101
|
+
* validates that each present field has its canonical type and strips unknowns; the
|
|
102
|
+
* `mediaAssetId`↔`mediaType` pairing (MEDIA-101) is enforced at DELIVERY, where the post
|
|
103
|
+
* core parses `SquareStreetzPostSchema` and a failure dead-letters the job instead.
|
|
104
|
+
*/
|
|
105
|
+
export const SquareStreetzPostPayloadSchema = z.object({
|
|
106
|
+
userId: z.string(),
|
|
107
|
+
mentions: z.array(MentionSchema).optional(),
|
|
108
|
+
newMediaAssetId: z.string().optional(),
|
|
109
|
+
// NEW_CRAFT_SKILL announcement descriptor — id/kind/tags/source let the post describe the
|
|
110
|
+
// craft WITHOUT leaking the client-supplied original file name.
|
|
111
|
+
craftSkill: z
|
|
112
|
+
.object({
|
|
113
|
+
id: z.string(),
|
|
114
|
+
name: z.string(),
|
|
115
|
+
mediaAssetId: z.string(),
|
|
116
|
+
type: ContentMediaKindSchema,
|
|
117
|
+
tags: z.array(z.enum(CRAFT_SKILL_TAG_VALUES)).optional(),
|
|
118
|
+
kind: CraftSkillKindSchema.optional(),
|
|
119
|
+
source: CraftSkillSourceReferenceSchema.optional(),
|
|
120
|
+
})
|
|
121
|
+
.optional(),
|
|
122
|
+
craftSkillId: z.string().optional(),
|
|
123
|
+
workProjectTitle: z.string().optional(),
|
|
124
|
+
workProjectId: z.string().optional(),
|
|
125
|
+
workProjectType: z.enum(WORK_PROJECT_TYPE_KEYS).optional(),
|
|
126
|
+
workProjectDescription: z.string().optional(),
|
|
127
|
+
workRealmId: z.string().optional(),
|
|
128
|
+
workRealmTitle: z.string().optional(),
|
|
129
|
+
hallItemId: z.string().optional(),
|
|
130
|
+
hallItemTitle: z.string().optional(),
|
|
131
|
+
hallSubItemType: HallSubItemTypeSchema.optional(),
|
|
132
|
+
content: z.string().optional(),
|
|
133
|
+
mediaAssetId: z.string().optional(),
|
|
134
|
+
mediaType: mediaTypeSchema.optional(),
|
|
135
|
+
createdAt: z.number().optional(),
|
|
136
|
+
auditionId: z.string().optional(),
|
|
137
|
+
commissionListingId: z.string().optional(),
|
|
138
|
+
auditionAnnounceKind: AuditionAnnounceKindSchema.optional(),
|
|
50
139
|
});
|
|
51
140
|
export const MentionHistoryItemSchema = MentionSchema.extend({ viewedAt: z.number() });
|
|
52
141
|
export const MentionHistoryDocumentSchema = z.object({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"social.js","sourceRoot":"","sources":["../../src/doc-schemas/social.ts"],"names":[],"mappings":"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","sourcesContent":["// Social Firestore document SCHEMAS — SquareStreetz posts, mention history, and\n// follow edges. Types inferred via z.infer. (Pledge-payment ledger docs moved to\n// ../doc-schemas/payments.ts. SquareStreetzPostPayload is a transport shape, not a\n// stored doc — it stays in ../types/social.ts.)\n\nimport { z } from 'zod';\nimport { MentionSchema } from '../media/atoms.js';\nimport { FollowableTargetTypeSchema } from '../schemas/social.js';\n\n/** The ONE canonical display/transport media-type family (the 'other' bucket covers\n * non-previewable kinds). Distinct from the 3-value stored ContentMediaKindSchema\n * (doc-schemas/media-assets.ts) and media-schemas' generic MediaKindSchema. */\nexport const MediaTypeSchema = z.enum(['image', 'video', 'audio', 'other']);\nexport type MediaType = z.infer<typeof MediaTypeSchema>;\nconst mediaTypeSchema = MediaTypeSchema;\n\n/** Discriminates the announcement voice/mention shape of a NEW_AUDITION Streetz post:\n * 'work' names the creating work inline; 'platform' | 'sponsored' name TTT Productions\n * the company instead (no work mention). The ONE declaration of this union. */\nexport const AuditionAnnounceKindSchema = z.enum(['work', 'platform', 'sponsored']);\nexport type AuditionAnnounceKind = z.infer<typeof AuditionAnnounceKindSchema>;\n\nexport const SquareStreetzPostTypeSchema = z.enum([\n 'PROFILE_PICTURE_UPDATE',\n 'NEW_CRAFT_SKILL',\n 'NEW_ARTISAN_CREATOR',\n 'COMMISSION_ACCEPTED',\n 'DELETE_CRAFT_SKILL',\n 'USER_POST',\n 'NEW_WORK_PROJECT',\n 'LIBRARY_PUBLISHED',\n 'NEW_AUDITION',\n 'NEW_COMMISSION',\n]);\nexport type SquareStreetzPostType = z.infer<typeof SquareStreetzPostTypeSchema>;\n\nexport const SquareStreetzPostSchema = z.object({\n postId: z.string(),\n createdBy: z.object({ uid: z.string() }),\n authorId: z.string(),\n content: z.string(),\n mentions: z.array(MentionSchema).optional(),\n relatedIds: z.array(z.string()),\n mediaAssetId: z.string().optional(),\n mediaType: mediaTypeSchema.optional(),\n createdAt: z.number(),\n likes: z.number(),\n postType: SquareStreetzPostTypeSchema.optional(),\n relatedAssetId: z.string().optional(),\n // Admin moderation hide (reversible). When true the post is suppressed from all\n // feeds/lists; restored by clearing it. `hidden` is the ONLY operative moderation\n // flag on a post — the legacy pre-finalize upload-gating (`visible`) and automated\n // text-moderation outcome (`moderationStatus`/`moderationReason`/`moderationLayer`)\n // fields were removed 2026-07-03: nothing wrote them (posts are created only AFTER\n // media finalize under pattern C), so they were dead. See\n // CODE_CHANGE_feed_slice_hygiene_misc.md item 1.\n hidden: z.boolean(),\n});\nexport type SquareStreetzPost = z.infer<typeof SquareStreetzPostSchema>;\n\nexport const MentionHistoryItemSchema = MentionSchema.extend({ viewedAt: z.number() });\nexport type MentionHistoryItem = z.infer<typeof MentionHistoryItemSchema>;\n\nexport const MentionHistoryDocumentSchema = z.object({\n userId: z.string(),\n items: z.array(MentionHistoryItemSchema),\n});\nexport type MentionHistoryDocument = z.infer<typeof MentionHistoryDocumentSchema>;\n\n// Authoritative result of the addToMentionHistory callable — the transaction computes\n// the deduped, capped list in memory before committing, so returning it costs no read.\n// Declared HERE (not schemas/social.ts) because it composes MentionHistoryItemSchema\n// and this module already imports schemas/social.js (FollowableTargetTypeSchema) — the\n// reverse runtime import would be a module cycle. Re-exported on the ./schemas subpath\n// via schemas/index.ts. Non-strict (server → client result posture).\nexport const AddToMentionHistoryResultSchema = z.object({\n success: z.literal(true),\n itemCount: z.number().int().nonnegative(),\n /** The full, deduped, capped history AFTER this write — a drop-in cache replacement. */\n items: z.array(MentionHistoryItemSchema),\n});\nexport type AddToMentionHistoryResult = z.infer<typeof AddToMentionHistoryResultSchema>;\n\nexport const FollowEdgeSchema = z.object({\n followerUid: z.string(),\n targetType: FollowableTargetTypeSchema,\n targetId: z.string(),\n followedOn: z.number(),\n});\nexport type FollowEdge = z.infer<typeof FollowEdgeSchema>;\n\n// followCounters/{targetType__targetId} — denormalized follower count for a followable target,\n// maintained by the follow/unfollow callables via FieldValue.increment (never written by clients).\n// The Hall Library \"Most Followed\" sort mirrors the workProject count onto hallItems.followerCount.\nexport const FollowCounterSchema = z.object({\n followerCount: z.number(),\n updatedOn: z.number(),\n});\nexport type FollowCounter = z.infer<typeof FollowCounterSchema>;\n\n// userProfiles/{uid}/userLikes/likeHistory/squareStreetzLikes/{postId} — a user's like on a\n// SquareStreetz post; existence == liked. The path nests three of the registry segments\n// (userLikes / likeHistory / squareStreetzLikes). (functions/src/social/likeSquareStreetzPost.ts)\nexport const SquareStreetzLikeSchema = z.object({\n likedOn: z.number(),\n});\nexport type SquareStreetzLike = z.infer<typeof SquareStreetzLikeSchema>;\n\n// squareStreetzFeed/trendingPosts — singleton holding the ordered top-N trending post IDs that the\n// client infinite-scrolls through. (functions/src/social/runUpdateTrendingFeed.ts)\nexport const TrendingPostsSchema = z.object({\n postIds: z.array(z.string()),\n lastUpdated: z.number(),\n});\nexport type TrendingPosts = z.infer<typeof TrendingPostsSchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"social.js","sourceRoot":"","sources":["../../src/doc-schemas/social.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,iFAAiF;AACjF,mFAAmF;AACnF,gDAAgD;AAEhD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,+BAA+B,EAAE,MAAM,WAAW,CAAC;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;+EAE+E;AAC/E,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAE5E,MAAM,eAAe,GAAG,eAAe,CAAC;AAExC;;+EAE+E;AAC/E,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;AAGpF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,IAAI,CAAC;IAChD,wBAAwB;IACxB,iBAAiB;IACjB,qBAAqB;IACrB,qBAAqB;IACrB,oBAAoB;IACpB,WAAW;IACX,kBAAkB;IAClB,mBAAmB;IACnB,cAAc;IACd,gBAAgB;CACjB,CAAC,CAAC;AAGH;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;IACxC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE;IAC3C,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC/B,oEAAoE;IACpE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,uEAAuE;IACvE,SAAS,EAAE,eAAe,CAAC,QAAQ,EAAE;IACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,QAAQ,EAAE,2BAA2B,CAAC,QAAQ,EAAE;IAChD,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,gFAAgF;IAChF,kFAAkF;IAClF,mFAAmF;IACnF,oFAAoF;IACpF,mFAAmF;IACnF,qEAAqE;IACrE,+CAA+C;IAC/C,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;CACpB,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IAC1B,IAAI,GAAG,CAAC,YAAY,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAClE,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,WAAW,CAAC;YACnB,OAAO,EAAE,gKAAgK;SAC1K,CAAC,CAAC;IACL,CAAC;IACD,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,GAAG,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QAClE,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,cAAc,CAAC;YACtB,OAAO,EAAE,uHAAuH;SACjI,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAGH;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IACrD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE;IAC3C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACtC,0FAA0F;IAC1F,gEAAgE;IAChE,UAAU,EAAE,CAAC;SACV,MAAM,CAAC;QACN,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;QACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;QAChB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;QACxB,IAAI,EAAE,sBAAsB;QAC5B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,QAAQ,EAAE;QACxD,IAAI,EAAE,oBAAoB,CAAC,QAAQ,EAAE;QACrC,MAAM,EAAE,+BAA+B,CAAC,QAAQ,EAAE;KACnD,CAAC;SACD,QAAQ,EAAE;IACb,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACvC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,QAAQ,EAAE;IAC1D,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACpC,eAAe,EAAE,qBAAqB,CAAC,QAAQ,EAAE;IACjD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,SAAS,EAAE,eAAe,CAAC,QAAQ,EAAE;IACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,oBAAoB,EAAE,0BAA0B,CAAC,QAAQ,EAAE;CAC5D,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,wBAAwB,GAAG,aAAa,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAGvF,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IACnD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,wBAAwB,CAAC;CACzC,CAAC,CAAC;AAGH,sFAAsF;AACtF,uFAAuF;AACvF,qFAAqF;AACrF,uFAAuF;AACvF,uFAAuF;AACvF,qEAAqE;AACrE,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC,MAAM,CAAC;IACtD,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACxB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IACzC,wFAAwF;IACxF,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,wBAAwB,CAAC;CACzC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,UAAU,EAAE,0BAA0B;IACtC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;CACvB,CAAC,CAAC;AAGH,+FAA+F;AAC/F,mGAAmG;AACnG,oGAAoG;AACpG,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;CACtB,CAAC,CAAC;AAGH,4FAA4F;AAC5F,wFAAwF;AACxF,kGAAkG;AAClG,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAC;AAGH,mGAAmG;AACnG,mFAAmF;AACnF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAC5B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;CACxB,CAAC,CAAC","sourcesContent":["// Social Firestore document SCHEMAS — SquareStreetz posts, mention history, and\n// follow edges. Types inferred via z.infer. (Pledge-payment ledger docs moved to\n// ../doc-schemas/payments.ts. SquareStreetzPostPayload is a transport shape, not a\n// stored doc — it stays in ../types/social.ts.)\n\nimport { z } from 'zod';\nimport { MentionSchema } from '../media/atoms.js';\nimport { FollowableTargetTypeSchema } from '../schemas/social.js';\nimport { ContentMediaKindSchema } from './media-assets.js';\nimport { CraftSkillKindSchema, CraftSkillSourceReferenceSchema } from './user.js';\nimport { HallSubItemTypeSchema } from './content.js';\nimport { CRAFT_SKILL_TAG_VALUES } from '../constants/options.js';\nimport { WORK_PROJECT_TYPE_KEYS } from '../types/content.js';\n\n/** The ONE canonical display/transport media-type family (the 'other' bucket covers\n * non-previewable kinds). Distinct from the 3-value stored ContentMediaKindSchema\n * (doc-schemas/media-assets.ts) and media-schemas' generic MediaKindSchema. */\nexport const MediaTypeSchema = z.enum(['image', 'video', 'audio', 'other']);\nexport type MediaType = z.infer<typeof MediaTypeSchema>;\nconst mediaTypeSchema = MediaTypeSchema;\n\n/** Discriminates the announcement voice/mention shape of a NEW_AUDITION Streetz post:\n * 'work' names the creating work inline; 'platform' | 'sponsored' name TTT Productions\n * the company instead (no work mention). The ONE declaration of this union. */\nexport const AuditionAnnounceKindSchema = z.enum(['work', 'platform', 'sponsored']);\nexport type AuditionAnnounceKind = z.infer<typeof AuditionAnnounceKindSchema>;\n\nexport const SquareStreetzPostTypeSchema = z.enum([\n 'PROFILE_PICTURE_UPDATE',\n 'NEW_CRAFT_SKILL',\n 'NEW_ARTISAN_CREATOR',\n 'COMMISSION_ACCEPTED',\n 'DELETE_CRAFT_SKILL',\n 'USER_POST',\n 'NEW_WORK_PROJECT',\n 'LIBRARY_PUBLISHED',\n 'NEW_AUDITION',\n 'NEW_COMMISSION',\n]);\nexport type SquareStreetzPostType = z.infer<typeof SquareStreetzPostTypeSchema>;\n\n/**\n * squareStreetzFeed/activePosts/socialPosts/{postId}.\n *\n * **Media-pair invariant (MEDIA-101) — enforced by the superRefine below:**\n * `mediaAssetId` and `mediaType` are ONE unit — both present, or both absent.\n * Gateway URLs are extensionless, so nothing downstream can recover the kind from\n * the id: a post persisted with an asset and NO kind classifies as `'other'` and\n * `AppMediaPreview` renders a Download link INSTEAD of the image/video. The mirror\n * case (a kind with no asset) is an orphan that describes media the post does not\n * carry. Declared HERE, on the canonical doc schema (ARCH-102), so every writer\n * inherits it from the one post-create chokepoint's parse rather than each write\n * site re-deciding — and so no reader ever needs a `?? 'other'` guess.\n *\n * Announcement posts REFERENCE a source asset (audition `videoAssetId`, commission\n * `commissionAttachment.mediaAssetId`), so the kind always comes from that source —\n * it is never invented or defaulted at the post write.\n */\nexport const SquareStreetzPostSchema = z.object({\n postId: z.string(),\n createdBy: z.object({ uid: z.string() }),\n authorId: z.string(),\n content: z.string(),\n mentions: z.array(MentionSchema).optional(),\n relatedIds: z.array(z.string()),\n /** Paired with `mediaType` — see the media-pair invariant above. */\n mediaAssetId: z.string().optional(),\n /** Paired with `mediaAssetId` — see the media-pair invariant above. */\n mediaType: mediaTypeSchema.optional(),\n createdAt: z.number(),\n likes: z.number(),\n postType: SquareStreetzPostTypeSchema.optional(),\n relatedAssetId: z.string().optional(),\n // Admin moderation hide (reversible). When true the post is suppressed from all\n // feeds/lists; restored by clearing it. `hidden` is the ONLY operative moderation\n // flag on a post — the legacy pre-finalize upload-gating (`visible`) and automated\n // text-moderation outcome (`moderationStatus`/`moderationReason`/`moderationLayer`)\n // fields were removed 2026-07-03: nothing wrote them (posts are created only AFTER\n // media finalize under pattern C), so they were dead. Durable owner:\n // ttt-prod docs/design/streetz-social-feed.md.\n hidden: z.boolean(),\n}).superRefine((val, ctx) => {\n if (val.mediaAssetId !== undefined && val.mediaType === undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['mediaType'],\n message: 'mediaType is required whenever a post carries mediaAssetId (MEDIA-101: an extensionless gateway URL with no kind renders a Download link instead of the media)',\n });\n }\n if (val.mediaType !== undefined && val.mediaAssetId === undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['mediaAssetId'],\n message: 'mediaType is only allowed on a post that carries mediaAssetId — an orphan kind describes media the post does not have',\n });\n }\n});\nexport type SquareStreetzPost = z.infer<typeof SquareStreetzPostSchema>;\n\n/**\n * The create/announcement transport payload for a SquareStreetz post — the exact input\n * `runManageSquareStreetzPost` accepts. Every enqueue site (the durable\n * `squareAnnouncementJobs` outbox) and the manual post callables build one of these; the\n * different post types populate different subsets, so every field beyond `userId` is\n * optional. The TYPE is inferred from this schema (ARCH-102 — one declaration; the\n * frontend extends it with a local `mediaFile?: File`).\n *\n * NON-strict and carrying NO cross-field pairing refinement ON PURPOSE: it is parsed at\n * ENQUEUE inside the announcing transaction (ttt-prod square-announcement-outbox.ts), so a\n * throw here would fail the user's primary action over an announcement defect (ENG-009). It\n * validates that each present field has its canonical type and strips unknowns; the\n * `mediaAssetId`↔`mediaType` pairing (MEDIA-101) is enforced at DELIVERY, where the post\n * core parses `SquareStreetzPostSchema` and a failure dead-letters the job instead.\n */\nexport const SquareStreetzPostPayloadSchema = z.object({\n userId: z.string(),\n mentions: z.array(MentionSchema).optional(),\n newMediaAssetId: z.string().optional(),\n // NEW_CRAFT_SKILL announcement descriptor — id/kind/tags/source let the post describe the\n // craft WITHOUT leaking the client-supplied original file name.\n craftSkill: z\n .object({\n id: z.string(),\n name: z.string(),\n mediaAssetId: z.string(),\n type: ContentMediaKindSchema,\n tags: z.array(z.enum(CRAFT_SKILL_TAG_VALUES)).optional(),\n kind: CraftSkillKindSchema.optional(),\n source: CraftSkillSourceReferenceSchema.optional(),\n })\n .optional(),\n craftSkillId: z.string().optional(),\n workProjectTitle: z.string().optional(),\n workProjectId: z.string().optional(),\n workProjectType: z.enum(WORK_PROJECT_TYPE_KEYS).optional(),\n workProjectDescription: z.string().optional(),\n workRealmId: z.string().optional(),\n workRealmTitle: z.string().optional(),\n hallItemId: z.string().optional(),\n hallItemTitle: z.string().optional(),\n hallSubItemType: HallSubItemTypeSchema.optional(),\n content: z.string().optional(),\n mediaAssetId: z.string().optional(),\n mediaType: mediaTypeSchema.optional(),\n createdAt: z.number().optional(),\n auditionId: z.string().optional(),\n commissionListingId: z.string().optional(),\n auditionAnnounceKind: AuditionAnnounceKindSchema.optional(),\n});\nexport type SquareStreetzPostPayload = z.infer<typeof SquareStreetzPostPayloadSchema>;\n\nexport const MentionHistoryItemSchema = MentionSchema.extend({ viewedAt: z.number() });\nexport type MentionHistoryItem = z.infer<typeof MentionHistoryItemSchema>;\n\nexport const MentionHistoryDocumentSchema = z.object({\n userId: z.string(),\n items: z.array(MentionHistoryItemSchema),\n});\nexport type MentionHistoryDocument = z.infer<typeof MentionHistoryDocumentSchema>;\n\n// Authoritative result of the addToMentionHistory callable — the transaction computes\n// the deduped, capped list in memory before committing, so returning it costs no read.\n// Declared HERE (not schemas/social.ts) because it composes MentionHistoryItemSchema\n// and this module already imports schemas/social.js (FollowableTargetTypeSchema) — the\n// reverse runtime import would be a module cycle. Re-exported on the ./schemas subpath\n// via schemas/index.ts. Non-strict (server → client result posture).\nexport const AddToMentionHistoryResultSchema = z.object({\n success: z.literal(true),\n itemCount: z.number().int().nonnegative(),\n /** The full, deduped, capped history AFTER this write — a drop-in cache replacement. */\n items: z.array(MentionHistoryItemSchema),\n});\nexport type AddToMentionHistoryResult = z.infer<typeof AddToMentionHistoryResultSchema>;\n\nexport const FollowEdgeSchema = z.object({\n followerUid: z.string(),\n targetType: FollowableTargetTypeSchema,\n targetId: z.string(),\n followedOn: z.number(),\n});\nexport type FollowEdge = z.infer<typeof FollowEdgeSchema>;\n\n// followCounters/{targetType__targetId} — denormalized follower count for a followable target,\n// maintained by the follow/unfollow callables via FieldValue.increment (never written by clients).\n// The Hall Library \"Most Followed\" sort mirrors the workProject count onto hallItems.followerCount.\nexport const FollowCounterSchema = z.object({\n followerCount: z.number(),\n updatedOn: z.number(),\n});\nexport type FollowCounter = z.infer<typeof FollowCounterSchema>;\n\n// userProfiles/{uid}/userLikes/likeHistory/squareStreetzLikes/{postId} — a user's like on a\n// SquareStreetz post; existence == liked. The path nests three of the registry segments\n// (userLikes / likeHistory / squareStreetzLikes). (functions/src/social/likeSquareStreetzPost.ts)\nexport const SquareStreetzLikeSchema = z.object({\n likedOn: z.number(),\n});\nexport type SquareStreetzLike = z.infer<typeof SquareStreetzLikeSchema>;\n\n// squareStreetzFeed/trendingPosts — singleton holding the ordered top-N trending post IDs that the\n// client infinite-scrolls through. (functions/src/social/runUpdateTrendingFeed.ts)\nexport const TrendingPostsSchema = z.object({\n postIds: z.array(z.string()),\n lastUpdated: z.number(),\n});\nexport type TrendingPosts = z.infer<typeof TrendingPostsSchema>;\n"]}
|