@ttt-productions/ttt-core 0.78.21 → 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.
Files changed (64) hide show
  1. package/dist/constants/admin-labels.d.ts +1 -1
  2. package/dist/constants/admin-labels.js +2 -2
  3. package/dist/constants/admin-labels.js.map +1 -1
  4. package/dist/constants/center-stage-rooms.js +1 -1
  5. package/dist/constants/center-stage-rooms.js.map +1 -1
  6. package/dist/constants/company-mascots.js +1 -1
  7. package/dist/constants/company-mascots.js.map +1 -1
  8. package/dist/constants/publish-attestations.js +1 -1
  9. package/dist/constants/publish-attestations.js.map +1 -1
  10. package/dist/constants/safety-confirmation-phrases.js +1 -1
  11. package/dist/constants/safety-confirmation-phrases.js.map +1 -1
  12. package/dist/doc-schemas/account-deletion.js +1 -1
  13. package/dist/doc-schemas/account-deletion.js.map +1 -1
  14. package/dist/doc-schemas/registry.js +1 -1
  15. package/dist/doc-schemas/registry.js.map +1 -1
  16. package/dist/doc-schemas/safety/age.js +1 -1
  17. package/dist/doc-schemas/safety/age.js.map +1 -1
  18. package/dist/doc-schemas/safety/evidence.js +1 -1
  19. package/dist/doc-schemas/safety/evidence.js.map +1 -1
  20. package/dist/doc-schemas/safety/foundation.d.ts +3 -3
  21. package/dist/doc-schemas/safety/foundation.d.ts.map +1 -1
  22. package/dist/doc-schemas/safety/foundation.js +3 -3
  23. package/dist/doc-schemas/safety/foundation.js.map +1 -1
  24. package/dist/doc-schemas/square-announcement-jobs.d.ts +1 -1
  25. package/dist/doc-schemas/square-announcement-jobs.js +2 -2
  26. package/dist/doc-schemas/square-announcement-jobs.js.map +1 -1
  27. package/dist/media/target-info.js +1 -1
  28. package/dist/media/target-info.js.map +1 -1
  29. package/dist/paths/collections.js +2 -2
  30. package/dist/paths/collections.js.map +1 -1
  31. package/dist/paths/path-builders.js +1 -1
  32. package/dist/paths/path-builders.js.map +1 -1
  33. package/dist/paths/related-ids.js +1 -1
  34. package/dist/paths/related-ids.js.map +1 -1
  35. package/dist/safety/active-safety-case-alert.js +1 -1
  36. package/dist/safety/active-safety-case-alert.js.map +1 -1
  37. package/dist/safety/ncii-intake-derivations.js +1 -1
  38. package/dist/safety/ncii-intake-derivations.js.map +1 -1
  39. package/dist/safety/resource-keys.js +1 -1
  40. package/dist/safety/resource-keys.js.map +1 -1
  41. package/dist/schemas/chat.js +1 -1
  42. package/dist/schemas/chat.js.map +1 -1
  43. package/dist/schemas/craft-skills.js +1 -1
  44. package/dist/schemas/craft-skills.js.map +1 -1
  45. package/dist/schemas/hall-library.js +1 -1
  46. package/dist/schemas/hall-library.js.map +1 -1
  47. package/dist/schemas/notification.js +1 -1
  48. package/dist/schemas/notification.js.map +1 -1
  49. package/dist/schemas/safety.d.ts +1 -1
  50. package/dist/schemas/safety.js +1 -1
  51. package/dist/schemas/safety.js.map +1 -1
  52. package/dist/types/admin-ops.d.ts +1 -1
  53. package/dist/types/admin-ops.d.ts.map +1 -1
  54. package/dist/types/admin-ops.js +1 -1
  55. package/dist/types/admin-ops.js.map +1 -1
  56. package/dist/types/admin-users.js +1 -1
  57. package/dist/types/admin-users.js.map +1 -1
  58. package/dist/types/social.d.ts +1 -1
  59. package/dist/types/social.js.map +1 -1
  60. package/dist/upload-variables/create-admin-audition-variables.js +1 -1
  61. package/dist/upload-variables/create-admin-audition-variables.js.map +1 -1
  62. package/dist/upload-variables/create-work-project-audition-variables.js +1 -1
  63. package/dist/upload-variables/create-work-project-audition-variables.js.map +1 -1
  64. package/package.json +1 -1
@@ -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 (Rule 36).
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 (Rule 36). */
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, Rule 36): which reason codes each disposition permits.
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 (Rule 36) and applied — alongside refineReportDispositionReasonCode — by
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":"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"}
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 (Rule 36). */
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, Rule 36): which reason codes each disposition permits.
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 (Rule 36) and applied — alongside refineReportDispositionReasonCode — by
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) {
@@ -1 +1 @@
1
- {"version":3,"file":"foundation.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/foundation.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — shared foundation enums + the canonical target locator.\n//\n// This file is the SINGLE SOURCE for every enum and locator that crosses more\n// than one T&S cluster (report spine, case spine, holds, evidence, sagas,\n// NCMEC, NCII). Cluster document-schema files import their value sets from\n// HERE so two clusters can never define the same enum with drifting values.\n// Every value is transcribed verbatim from docs/code_changes_needed/\n// trust-and-safety/IMPLEMENTATION_PLAN.md Appendix A (the frozen spec) — no\n// invented values, no placeholders.\n//\n// Cross-boundary: these types are consumed by both functions/src and src/ in\n// ttt-prod, so they live in ttt-core (the single source of truth for the\n// backend↔frontend boundary) and surface on the `@ttt-productions/ttt-core/\n// doc-schemas` subpath.\n\nimport { z } from 'zod';\nimport {\n MAX_SAFETY_RESOLUTION_SUMMARY_LENGTH,\n MAX_SAFETY_ADMIN_NOTE_LENGTH,\n} from '../../constants/business.js';\n\n// ===========================================================================\n// A1 — Report reasons + reportable item types\n// ===========================================================================\n\n/** The controlling report-reason taxonomy (fixes the client/server drift\n * TS-032). The two protected reasons fork into a childSafetyCase / nciiCase. */\nexport const ReportReasonSchema = z.enum([\n 'Spam',\n 'Harassment',\n 'Hate Speech',\n 'Violence or Threats',\n 'Sexual Content',\n 'Self-Harm',\n 'Impersonation',\n 'Intellectual Property',\n 'Child Safety Concern', // → protected fork: childSafetyCase\n 'Nonconsensual Intimate Image (NCII)', // → protected fork: nciiCase\n 'Not related to on-site entertainment',\n 'Other',\n]);\nexport type ReportReason = z.infer<typeof ReportReasonSchema>;\n\n/** The two reasons that take the mandatory in-process protected branch. */\nexport const PROTECTED_REPORT_REASONS = [\n 'Child Safety Concern',\n 'Nonconsensual Intimate Image (NCII)',\n] as const satisfies readonly ReportReason[];\n\n/** Which protected fork a protected-reason report committed. */\nexport const ProtectedForkSchema = z.enum(['childSafetyCase', 'nciiCase']);\nexport type ProtectedFork = z.infer<typeof ProtectedForkSchema>;\n\n/** EXACTLY the `reportableItems` keys in ttt-prod src/lib/report-config.ts. A\n * ttt-prod CI test asserts this enum and `reportableItems` stay in sync (the\n * sync test lives app-side because report-config.ts is app-side). */\nexport const ReportableItemTypeSchema = z.enum([\n 'username',\n 'craft-skill',\n 'commission-listing',\n 'commission-proposal',\n 'square-streetz-post',\n 'profile-picture',\n 'guild-invite-message',\n 'guild-chat-message',\n // A single message in a WORK-PARTY admin correspondence thread (pendingAdminDispatches\n // partyKind 'workProject' — the one multi-member chat surface transported through\n // Firestore `conversationMessages`). The resolver enforces the work-party kind\n // server-side; user↔admin support threads are NOT reportable (an admin is already a\n // participant in every thread — DJ ruling 2026-07-13).\n 'admin-work-message',\n 'hall-library-item',\n // [EUAS-017] a single Hall sub-item (a Tale chapter / Tune track / Television episode). The\n // `hallItem` TargetLocatorV1 already carries an optional `subItemId`; the report UI passes the\n // sub-item id + its parent hall item, and the resolver derives the canonical sub-item path\n // server-side. Admins can already hide a single sub-item (runSetHallSubItemHidden) — this makes the\n // matching user-facing report reachable.\n 'hall-library-sub-item',\n 'audition',\n 'audition-entry',\n 'work-project',\n 'work-asset',\n 'work-realm',\n]);\nexport type ReportableItemType = z.infer<typeof ReportableItemTypeSchema>;\n\n/** The DO-transported chat report types — no Firestore message doc / owner exists to\n * hold at intake (H-04 V1); the resolver goes through the signed chat-Worker context\n * read. `admin-work-message` is NOT here: its messages are Firestore docs. Derived\n * subset — compile-linked to the canonical enum, never a re-declared string set. */\nexport const CHAT_REPORT_ITEM_TYPES = [\n 'guild-chat-message',\n 'guild-invite-message',\n] as const satisfies readonly ReportableItemType[];\n\n/** Item types whose report work-view renders the content-action (moderate) panel —\n * the backend moderation cores accept these. Compile-linked subset of the enum. */\nexport const CONTENT_ACTION_PANEL_ITEM_TYPES = [\n 'square-streetz-post',\n 'audition',\n 'audition-entry',\n 'commission-listing',\n 'commission-proposal',\n 'work-asset',\n 'profile-picture',\n 'hall-library-item',\n 'hall-library-sub-item',\n 'craft-skill',\n // Work-party admin correspondence message — single-doc hidden flip (2026-07-13).\n 'admin-work-message',\n] as const satisfies readonly ReportableItemType[];\nexport type ContentActionPanelItemType = (typeof CONTENT_ACTION_PANEL_ITEM_TYPES)[number];\n\n// ===========================================================================\n// A11 — Target locator (the ONE typed locator used by allegations, temp holds,\n// removal targets, and the report resolver) + privacy-safe summary\n// ===========================================================================\n\n/** Discriminated locator — replaces every all-optional `contentRef`. Every\n * hideable surface in report-config.ts has a typed locator ([H-02]). */\nexport const TargetLocatorV1Schema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('mediaAsset'), mediaAssetId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('hallItem'), hallItemId: z.string().min(1), subItemId: z.string().min(1).optional() }).strict(),\n z.object({ kind: z.literal('squarePost'), postId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('profileImage'), profileUid: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('username'), profileUid: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('craftSkill'), profileUid: z.string().min(1), craftSkillId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('commissionListing'), commissionListingId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('commissionProposal'), commissionListingId: z.string().min(1), commissionProposalId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('workProject'), workProjectId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('workAsset'), workProjectId: z.string().min(1), workAssetId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('workRealm'), workRealmId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('audition'), auditionId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('auditionEntry'), auditionId: z.string().min(1), auditionEntryId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('guildInviteMessage'), channelId: z.string().min(1), messageId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('chatAttachment'), channelId: z.string().min(1), messageId: z.string().min(1), attachmentId: z.string().min(1) }).strict(),\n // [H-04 V1] Plain guild chat message (text-only or Worker-unresolved). Distinct from\n // `chatAttachment` (which carries an actual attachment id) so a text-only protected chat\n // report has a clean, unambiguous locator without misusing the attachment variant.\n z.object({ kind: z.literal('guildChatMessage'), channelId: z.string().min(1), messageId: z.string().min(1) }).strict(),\n // A work-party admin correspondence message — a Firestore doc at\n // pendingAdminDispatches/{adminDispatchId}/conversationMessages/{messageId} (unlike the\n // DO-addressed guildChatMessage/guildInviteMessage locators, messageId here is a doc id,\n // not a numeric seq).\n z.object({ kind: z.literal('adminWorkMessage'), adminDispatchId: z.string().min(1), messageId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('url'), url: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('additionalText'), textRef: z.string().min(1) }).strict(),\n]);\nexport type TargetLocatorV1 = z.infer<typeof TargetLocatorV1Schema>;\n\n/** The set of locator discriminants — used wherever only the `kind` is needed. */\nexport const TargetLocatorKindSchema = z.enum([\n 'mediaAsset',\n 'hallItem',\n 'squarePost',\n 'profileImage',\n 'username',\n 'craftSkill',\n 'commissionListing',\n 'commissionProposal',\n 'workProject',\n 'workAsset',\n 'workRealm',\n 'audition',\n 'auditionEntry',\n 'guildInviteMessage',\n 'chatAttachment',\n // [H-04 V1] Plain guild chat message locator (text-only / Worker-unresolved protected report).\n 'guildChatMessage',\n // Work-party admin correspondence message (Firestore conversationMessages doc).\n 'adminWorkMessage',\n 'url',\n 'additionalText',\n]);\nexport type TargetLocatorKind = z.infer<typeof TargetLocatorKindSchema>;\n\n/** Privacy-safe summary ONLY — no narrative / PII; used on roots + public rows. */\nexport const TargetLocatorSummaryV1Schema = z.object({\n kind: TargetLocatorKindSchema,\n surfaceLabel: z.string(),\n hasResolvedTarget: z.boolean(),\n}).strict();\nexport type TargetLocatorSummaryV1 = z.infer<typeof TargetLocatorSummaryV1Schema>;\n\n// ===========================================================================\n// A9 — Reporting determination + NCMEC submission state\n// ===========================================================================\n\n/** Case-level reporting determination (Finding-H6). The ONLY carrier of \"no\n * NCMEC report required\" — `notRequired` was removed from NcmecSubmissionState. */\nexport const ReportDispositionSchema = z.enum([\n 'undetermined',\n 'reportRequired',\n 'notRequired',\n 'correctedNoApparentViolation',\n]);\nexport type ReportDisposition = z.infer<typeof ReportDispositionSchema>;\n\n/** Reason codes for the privileged setReportDisposition command (§A9). The first five are the\n * not-required / exception reasons (no NCMEC report ever arose, or a triggering signal was\n * corrected); the last two are the report-required reasons (a report IS legally required). The\n * disposition↔reason pairing is enforced by the ONE cross-field rule below (Rule 36). */\nexport const ReportDispositionReasonCodeSchema = z.enum([\n 'outOfScopeNotCsea',\n 'basisInvalidatedFalseMatch',\n 'duplicateOfFiledReport',\n 'leDirectedNoReport',\n 'nonReportableSafetyConfirmed',\n // Report-required reasons — valid ONLY with disposition 'reportRequired'.\n 'apparentCsamConfirmed', // human review confirmed apparent CSAM\n 'hashMatchValidated', // validated hash match\n]);\nexport type ReportDispositionReasonCode = z.infer<typeof ReportDispositionReasonCodeSchema>;\n\n/** The reason codes that ASSERT a reporting obligation — legal ONLY with 'reportRequired'.\n * Compile-linked subset of the canonical reason enum. */\nexport const REPORT_REQUIRED_DISPOSITION_REASON_CODES = [\n 'apparentCsamConfirmed',\n 'hashMatchValidated',\n] as const satisfies readonly ReportDispositionReasonCode[];\n\n/** The not-required / exception reason codes — legal with every disposition that does NOT assert a\n * reporting obligation ('notRequired', 'correctedNoApparentViolation'). Compile-linked subset. */\nexport const NOT_REQUIRED_DISPOSITION_REASON_CODES = [\n 'outOfScopeNotCsea',\n 'basisInvalidatedFalseMatch',\n 'duplicateOfFiledReport',\n 'leDirectedNoReport',\n 'nonReportableSafetyConfirmed',\n] as const satisfies readonly ReportDispositionReasonCode[];\n\n/** The ONE cross-field pairing (§A9, Rule 36): which reason codes each disposition permits.\n * Declared HERE once; both the setReportDisposition input (case.ts) and the SafetyDispositionAction\n * console command (admin.ts) apply `refineReportDispositionReasonCode` derived from this map rather\n * than re-declaring the pairing. 'undetermined' is the initial state, never an operator-settable\n * target, so it permits NO reason code (the operator command excludes it). Typed as an exhaustive\n * Record so a new disposition fails to compile until its permitted codes are declared. */\nexport const REPORT_DISPOSITION_ALLOWED_REASON_CODES: Record<\n ReportDisposition,\n readonly ReportDispositionReasonCode[]\n> = {\n undetermined: [],\n reportRequired: REPORT_REQUIRED_DISPOSITION_REASON_CODES,\n notRequired: NOT_REQUIRED_DISPOSITION_REASON_CODES,\n correctedNoApparentViolation: NOT_REQUIRED_DISPOSITION_REASON_CODES,\n};\n\n/** Shared cross-field refinement enforcing the disposition↔reason pairing above. Applied by BOTH\n * the setReportDisposition input schemas and the SafetyDispositionAction console command so the\n * rule lives in exactly one place. Reports the failure on the `dispositionReasonCode` path. */\nexport function refineReportDispositionReasonCode(\n value: { disposition: ReportDisposition; dispositionReasonCode: ReportDispositionReasonCode },\n ctx: z.RefinementCtx,\n): void {\n if (!REPORT_DISPOSITION_ALLOWED_REASON_CODES[value.disposition].includes(value.dispositionReasonCode)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['dispositionReasonCode'],\n message: `Reason code '${value.dispositionReasonCode}' is not valid for disposition '${value.disposition}'.`,\n });\n }\n}\n\n/** Shared cross-field rule (§A9): disposition 'reportRequired' MUST carry at least one evidence ref —\n * a reporting obligation can only be asserted once the evidence has been revealed. Every OTHER\n * disposition ('notRequired', 'correctedNoApparentViolation', 'undetermined') MAY leave evidenceRefs\n * empty. Declared HERE once (Rule 36) and applied — alongside refineReportDispositionReasonCode — by\n * BOTH the setReportDisposition input schemas (case.ts) and the SafetyStagedAction console command\n * (admin.ts), never re-declared. Reports the failure on the `evidenceRefs` path. */\nexport function refineReportDispositionEvidenceRefs(\n value: { disposition: ReportDisposition; evidenceRefs: readonly string[] },\n ctx: z.RefinementCtx,\n): void {\n if (value.disposition === 'reportRequired' && value.evidenceRefs.length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['evidenceRefs'],\n message:\n \"Disposition 'reportRequired' requires at least one evidence ref (evidence must have been revealed).\",\n });\n }\n}\n\n// ===========================================================================\n// [EUAS-008] Structured safety-case CLOSURE record — the operator's terminal\n// determination persisted when a CSAM / NCII case is closed via the guided\n// resolution flow (resolveAdminTask). Embedded on the NCII case (`closure`) and on\n// a child-safety `decisions/{id}` row (kind `caseClosed`) so both case types carry\n// the SAME structured outcome/summary/note + actor/timestamp — not just a status\n// flip. This does NOT replace the case lifecycle's own terminal status; it records\n// WHO closed it, WHY, and with what outcome.\n// ===========================================================================\n\n/** founded = a violation was substantiated; unfounded = no violation on review. */\nexport const SafetyCaseClosureOutcomeSchema = z.enum(['founded', 'unfounded']);\nexport type SafetyCaseClosureOutcome = z.infer<typeof SafetyCaseClosureOutcomeSchema>;\n\n/** The structured closure record written on a safety-case close. */\nexport const SafetyCaseClosureV1Schema = z.object({\n outcome: SafetyCaseClosureOutcomeSchema,\n resolutionSummary: z.string().min(1).max(MAX_SAFETY_RESOLUTION_SUMMARY_LENGTH),\n adminNote: z.string().max(MAX_SAFETY_ADMIN_NOTE_LENGTH).optional(),\n closedByUid: z.string().min(1),\n closedAt: z.number(),\n}).strict();\nexport type SafetyCaseClosureV1 = z.infer<typeof SafetyCaseClosureV1Schema>;\n\n/** NCMEC submission lifecycle — MANUAL-PORTAL model (§A9). NO `notRequired` (that is\n * ReportDisposition). There is no automated ispws API: a report-needed obligation sits in\n * `awaitingManualFiling` from enqueue until the operator files on the NCMEC portal and records the\n * confirmation (markNcmecPortalComplete → `completed`). Jobs are born `awaitingManualFiling`; the\n * case-list `ncmecStatus` projection uses the same value (no separate `queued` state). There is no\n * in-app retraction — corrections are portal-manual (correction-lifecycle decision). The old\n * API-drive states\n * (opening/open/uploading/addingFileDetails/finishing/retryableFailure/ambiguousResult/permanentFailure)\n * were removed with the live-API client. */\nexport const NcmecSubmissionStateSchema = z.enum([\n 'awaitingManualFiling',\n 'completed',\n]);\nexport type NcmecSubmissionState = z.infer<typeof NcmecSubmissionStateSchema>;\n\n// ===========================================================================\n// A3 — Safety-hold + resource-command vocabularies (the ONE destructive-guard\n// authority). The NCII/storage resource types live in THIS enum (H1 fix).\n// ===========================================================================\n\nexport const SafetyHoldResourceTypeSchema = z.enum([\n 'contentDoc',\n 'mediaAsset',\n 'account',\n 'chatMessageRange',\n 'channel',\n 'nciiTemporaryTarget',\n 'storageObject',\n 'reportEvidenceObject',\n]);\nexport type SafetyHoldResourceType = z.infer<typeof SafetyHoldResourceTypeSchema>;\n\n/** Lifecycle/retention regime governed by the A3 compatibility matrix. */\nexport const SafetyHoldClassSchema = z.enum([\n 'childSafety',\n 'nciiTemporary',\n 'legalRetention',\n 'preservationEvidence',\n // An OPEN ordinary (non-protected) content report places an account-level hold\n // (resourceType 'account', ownerUid = the reported user) so a user can't delete\n // their data out from under an unreviewed report (e.g. a DMCA/IP complaint, then\n // delete-to-clear-tracks). blocksDeletion + blocksAnonymization; released when the\n // report group's admin close-out resolves it. Durable (no expiresAt).\n 'ordinaryReport',\n]);\nexport type SafetyHoldClass = z.infer<typeof SafetyHoldClassSchema>;\n\n/** Resource-scoped destructive command kinds (A3). */\nexport const SafetyCommandKindSchema = z.enum([\n 'nciiRemoval',\n 'csamActiveByteRemoval',\n 'evidenceDisposition',\n]);\nexport type SafetyCommandKind = z.infer<typeof SafetyCommandKindSchema>;\n\n// ===========================================================================\n// Reviewer-capability matrix (§A11 [M4] + §A9). One solo operator holds all\n// at launch; every privileged command checks the SPECIFIC capability + reauth.\n// ===========================================================================\n\nexport const SafetyReviewerCapabilitySchema = z.enum([\n 'nciiRequestReviewer',\n 'nciiEvidenceReviewer',\n 'nciiAppealReviewer',\n 'childSafetyReviewer',\n 'legalDispositionAuthority',\n]);\nexport type SafetyReviewerCapability = z.infer<typeof SafetyReviewerCapabilitySchema>;\n\n// ===========================================================================\n// A7 — Registration-completion outcome (DOMAIN enum; replaces the unsafe\n// generic gRPC retryable/terminal code lists). Only a domain outcome feeds the\n// orphan-Auth deletion policy.\n// ===========================================================================\n\nexport const RegistrationCompletionOutcomeSchema = z.enum([\n 'completed',\n 'alreadyCompletedSameUid',\n 'retryableInfrastructureFailure',\n 'reauthenticationRequired',\n 'appCheckRetryRequired',\n 'nonceExpired',\n 'nonceUnknown',\n 'nonceConsumedDifferentUid',\n 'sessionHashMismatch',\n 'attestationSignatureInvalid',\n 'privateDataConflict',\n 'policyVersionRejected',\n]);\nexport type RegistrationCompletionOutcome = z.infer<typeof RegistrationCompletionOutcomeSchema>;\n\n// ===========================================================================\n// A11 — NCII / TAKE IT DOWN shared vocabularies (consumed by BOTH NCII clusters)\n// ===========================================================================\n\n/** Closed enum of required field codes — completeness + public missing-fields. */\nexport const TakeItDownFieldCodeSchema = z.enum([\n 'requesterName',\n 'contactEmail',\n 'contactPhone',\n 'requesterRole',\n 'electronicSignature',\n 'authorityBasis',\n 'authorityCertification',\n 'authorityEvidence',\n 'targetLocator',\n 'nonconsentStatement',\n 'supportingFacts',\n 'goodFaithCertification',\n]);\nexport type TakeItDownFieldCode = z.infer<typeof TakeItDownFieldCodeSchema>;\n\n/** Closed PUBLIC-SAFE reason codes — never reveal evidence/uploader/crossover. */\nexport const TakeItDownPublicReasonCodeSchema = z.enum([\n 'needMoreInformation',\n 'couldNotVerifyRequesterRole',\n 'couldNotLocateContent',\n 'outsideCoveredScope',\n 'duplicateOfExistingRequest',\n 'removedSuccessfully',\n 'underReview',\n 'closedSeeNotice',\n]);\nexport type TakeItDownPublicReasonCode = z.infer<typeof TakeItDownPublicReasonCodeSchema>;\n\n/** Validity-failure reason codes ([H2]). `incomplete` is a COMPLETENESS state,\n * NEVER a validity state. */\nexport const TakeItDownInvalidReasonCodeSchema = z.enum([\n 'missingSignature',\n 'missingLocator',\n 'missingNonconsentStatement',\n 'missingContactInformation',\n 'requesterNotDepictedPersonOrAuthorizedRepresentative',\n 'authorityNotEstablished',\n 'locatorNotResolvableAfterReasonableEffort',\n 'requestOutsideCoveredDepiction',\n 'duplicateSuperseded',\n 'fraudulentOrBadFaith',\n 'otherCounselApproved',\n]);\nexport type TakeItDownInvalidReasonCode = z.infer<typeof TakeItDownInvalidReasonCodeSchema>;\n\n/** Requester role (depicted person vs authorized representative). */\nexport const TakeItDownRequesterRoleSchema = z.enum(['depictedPerson', 'authorizedRepresentative']);\nexport type TakeItDownRequesterRole = z.infer<typeof TakeItDownRequesterRoleSchema>;\n\n/** Two-axis state: completeness vs validity (H2). */\nexport const TakeItDownCompletenessStatusSchema = z.enum(['incomplete', 'complete']);\nexport type TakeItDownCompletenessStatus = z.infer<typeof TakeItDownCompletenessStatusSchema>;\n\nexport const TakeItDownValidityStatusSchema = z.enum(['pending', 'valid', 'invalid', 'unableToLocate']);\nexport type TakeItDownValidityStatus = z.infer<typeof TakeItDownValidityStatusSchema>;\n\n/** The public no-login status-page status set (root + statusProjection). No\n * appeal model — no `appealedCorrected` (the appeal/reinstatement flow was\n * removed; protected reports have no uploader appeal/notice/reinstatement). */\nexport const TakeItDownPublicStatusSchema = z.enum([\n 'received',\n 'needsMoreInfo',\n 'validInProgress',\n 'completed',\n 'unableToLocate',\n 'invalidGeneralReason',\n]);\nexport type TakeItDownPublicStatus = z.infer<typeof TakeItDownPublicStatusSchema>;\n\n/** Request action types ([L1]). */\nexport const NciiActionTypeSchema = z.enum([\n 'intakeReceived',\n 'completenessDecided',\n 'validityDecided',\n 'tempHoldPlaced',\n 'tempHoldReleased',\n 'removalStarted',\n 'removalCompleted',\n 'hashBlockReversed',\n 'childSafetyCaseLinked',\n 'legalDispositionRecorded',\n]);\nexport type NciiActionType = z.infer<typeof NciiActionTypeSchema>;\n\nexport const NciiActionResultSchema = z.enum(['succeeded', 'failed', 'deferred', 'rejected']);\nexport type NciiActionResult = z.infer<typeof NciiActionResultSchema>;\n\n/** Honest derived completion ([H4]) — never 'completed' for a partial failure. */\nexport const NciiRemovalCompletionOutcomeSchema = z.enum([\n 'completed',\n 'completedWithApprovedException',\n 'unableToComplete',\n]);\nexport type NciiRemovalCompletionOutcome = z.infer<typeof NciiRemovalCompletionOutcomeSchema>;\n\nexport const NciiTargetSurfaceSchema = z.enum([\n 'original',\n 'hallCopy',\n 'profileMedia',\n 'chatAttachment',\n 'variant',\n 'cacheServing',\n 'exactHashMatch',\n]);\nexport type NciiTargetSurface = z.infer<typeof NciiTargetSurfaceSchema>;\n\nexport const NciiTargetOutcomeSchema = z.enum([\n 'pending',\n 'removed',\n 'tombstoned',\n 'verifiedGone',\n 'leftoverRetrying',\n 'unableToComplete',\n 'terminalException',\n]);\nexport type NciiTargetOutcome = z.infer<typeof NciiTargetOutcomeSchema>;\n\n/** CLOSED terminal-exception enum — a technical outage is NOT an exception. */\nexport const NciiTerminalExceptionSchema = z.enum([\n 'legallyPermittedRetention',\n 'contentNotPresentVerified',\n 'counselApprovedException',\n]);\nexport type NciiTerminalException = z.infer<typeof NciiTerminalExceptionSchema>;\n\n/** Internal operational case status ([H7]).\n *\n * [R12] close-lifecycle states: clicking **Close** (after the strict-closable gate passes)\n * applies the staged actions and moves the case to `processing` — it STAYS pinned/in-queue,\n * NEVER cleared on the click. The NCII removal worker flips the case to the terminal `closed`\n * ONLY on VERIFIED removal completion (clearing the pin via onSafetyCaseClosed). If the\n * removal saga exhausts its retries (dead-letter), the case moves to `failed` — kept pinned,\n * surfaced in the Safety Console failed-jobs view, with a Restart that re-arms the job. Both\n * are explicit values (never derived). */\nexport const NciiInternalStatusSchema = z.enum([\n 'open',\n 'removalInProgress',\n 'processing',\n 'failed',\n 'removed',\n 'rejected',\n 'closed',\n]);\nexport type NciiInternalStatus = z.infer<typeof NciiInternalStatusSchema>;\n\n/** Child-safety linkage status on an NCII case ([H7]). */\nexport const NciiChildSafetyLinkStatusSchema = z.enum([\n 'none',\n 'assessmentPending',\n 'linked',\n 'resolvedNoChildSafetyCase',\n]);\nexport type NciiChildSafetyLinkStatus = z.infer<typeof NciiChildSafetyLinkStatusSchema>;\n\n// ===========================================================================\n// A11 [F4] — child-safety crossover (possible-minor ≠ automatic CSAM).\n// Embedded on nciiCases. childSafetyCaseId lives HERE (one canonical place).\n// ===========================================================================\n\nexport const NciiMinorAssessmentSchema = z.enum(['adult', 'unknown', 'possibleMinor', 'confirmedMinor']);\nexport type NciiMinorAssessment = z.infer<typeof NciiMinorAssessmentSchema>;\n\nexport const NciiCsamAssessmentSchema = z.enum([\n 'notAssessed',\n 'notApparent',\n 'apparentViolation',\n 'validatedHashMatch',\n]);\nexport type NciiCsamAssessment = z.infer<typeof NciiCsamAssessmentSchema>;\n\nexport const NciiChildSafetyCrossoverSchema = z.object({\n minorAssessment: NciiMinorAssessmentSchema,\n csamAssessment: NciiCsamAssessmentSchema,\n childSafetyCaseId: z.string().min(1).optional(),\n assessedByUid: z.string().min(1).optional(),\n assessedAt: z.number().optional(),\n}).strict();\nexport type NciiChildSafetyCrossover = z.infer<typeof NciiChildSafetyCrossoverSchema>;\n\n/** [H-2] Per-leg lifecycle status for the possible-minor crossover side-effects (serving-deny,\n * PhotoDNA) persisted on the crossover child-safety case (see ChildSafetyCaseV1.crossoverLegs).\n * `pending` is the in-transaction initial marker the assessment writes before the post-commit leg\n * runs; the leg then flips it to `done` (succeeded) or `failed` (captureException'd, awaiting a\n * reconcile/replay). A leg is ABSENT (not `pending`) when it never applied — an external / no-media\n * target has no bytes to deny or scan. */\nexport const SafetyCrossoverLegStatusSchema = z.enum(['pending', 'done', 'failed']);\nexport type SafetyCrossoverLegStatus = z.infer<typeof SafetyCrossoverLegStatusSchema>;\n"]}
1
+ {"version":3,"file":"foundation.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/foundation.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — shared foundation enums + the canonical target locator.\n//\n// This file is the SINGLE SOURCE for every enum and locator that crosses more\n// than one T&S cluster (report spine, case spine, holds, evidence, sagas,\n// NCMEC, NCII). Cluster document-schema files import their value sets from\n// HERE so two clusters can never define the same enum with drifting values.\n// Every value is transcribed verbatim from docs/code_changes_needed/\n// trust-and-safety/IMPLEMENTATION_PLAN.md Appendix A (the frozen spec) — no\n// invented values, no placeholders.\n//\n// Cross-boundary: these types are consumed by both functions/src and src/ in\n// ttt-prod, so they live in ttt-core (the single source of truth for the\n// backend↔frontend boundary) and surface on the `@ttt-productions/ttt-core/\n// doc-schemas` subpath.\n\nimport { z } from 'zod';\nimport {\n MAX_SAFETY_RESOLUTION_SUMMARY_LENGTH,\n MAX_SAFETY_ADMIN_NOTE_LENGTH,\n} from '../../constants/business.js';\n\n// ===========================================================================\n// A1 — Report reasons + reportable item types\n// ===========================================================================\n\n/** The controlling report-reason taxonomy (fixes the client/server drift\n * TS-032). The two protected reasons fork into a childSafetyCase / nciiCase. */\nexport const ReportReasonSchema = z.enum([\n 'Spam',\n 'Harassment',\n 'Hate Speech',\n 'Violence or Threats',\n 'Sexual Content',\n 'Self-Harm',\n 'Impersonation',\n 'Intellectual Property',\n 'Child Safety Concern', // → protected fork: childSafetyCase\n 'Nonconsensual Intimate Image (NCII)', // → protected fork: nciiCase\n 'Not related to on-site entertainment',\n 'Other',\n]);\nexport type ReportReason = z.infer<typeof ReportReasonSchema>;\n\n/** The two reasons that take the mandatory in-process protected branch. */\nexport const PROTECTED_REPORT_REASONS = [\n 'Child Safety Concern',\n 'Nonconsensual Intimate Image (NCII)',\n] as const satisfies readonly ReportReason[];\n\n/** Which protected fork a protected-reason report committed. */\nexport const ProtectedForkSchema = z.enum(['childSafetyCase', 'nciiCase']);\nexport type ProtectedFork = z.infer<typeof ProtectedForkSchema>;\n\n/** EXACTLY the `reportableItems` keys in ttt-prod src/lib/report-config.ts. A\n * ttt-prod CI test asserts this enum and `reportableItems` stay in sync (the\n * sync test lives app-side because report-config.ts is app-side). */\nexport const ReportableItemTypeSchema = z.enum([\n 'username',\n 'craft-skill',\n 'commission-listing',\n 'commission-proposal',\n 'square-streetz-post',\n 'profile-picture',\n 'guild-invite-message',\n 'guild-chat-message',\n // A single message in a WORK-PARTY admin correspondence thread (pendingAdminDispatches\n // partyKind 'workProject' — the one multi-member chat surface transported through\n // Firestore `conversationMessages`). The resolver enforces the work-party kind\n // server-side; user↔admin support threads are NOT reportable (an admin is already a\n // participant in every thread — DJ ruling 2026-07-13).\n 'admin-work-message',\n 'hall-library-item',\n // [EUAS-017] a single Hall sub-item (a Tale chapter / Tune track / Television episode). The\n // `hallItem` TargetLocatorV1 already carries an optional `subItemId`; the report UI passes the\n // sub-item id + its parent hall item, and the resolver derives the canonical sub-item path\n // server-side. Admins can already hide a single sub-item (runSetHallSubItemHidden) — this makes the\n // matching user-facing report reachable.\n 'hall-library-sub-item',\n 'audition',\n 'audition-entry',\n 'work-project',\n 'work-asset',\n 'work-realm',\n]);\nexport type ReportableItemType = z.infer<typeof ReportableItemTypeSchema>;\n\n/** The DO-transported chat report types — no Firestore message doc / owner exists to\n * hold at intake (H-04 V1); the resolver goes through the signed chat-Worker context\n * read. `admin-work-message` is NOT here: its messages are Firestore docs. Derived\n * subset — compile-linked to the canonical enum, never a re-declared string set. */\nexport const CHAT_REPORT_ITEM_TYPES = [\n 'guild-chat-message',\n 'guild-invite-message',\n] as const satisfies readonly ReportableItemType[];\n\n/** Item types whose report work-view renders the content-action (moderate) panel —\n * the backend moderation cores accept these. Compile-linked subset of the enum. */\nexport const CONTENT_ACTION_PANEL_ITEM_TYPES = [\n 'square-streetz-post',\n 'audition',\n 'audition-entry',\n 'commission-listing',\n 'commission-proposal',\n 'work-asset',\n 'profile-picture',\n 'hall-library-item',\n 'hall-library-sub-item',\n 'craft-skill',\n // Work-party admin correspondence message — single-doc hidden flip (2026-07-13).\n 'admin-work-message',\n] as const satisfies readonly ReportableItemType[];\nexport type ContentActionPanelItemType = (typeof CONTENT_ACTION_PANEL_ITEM_TYPES)[number];\n\n// ===========================================================================\n// A11 — Target locator (the ONE typed locator used by allegations, temp holds,\n// removal targets, and the report resolver) + privacy-safe summary\n// ===========================================================================\n\n/** Discriminated locator — replaces every all-optional `contentRef`. Every\n * hideable surface in report-config.ts has a typed locator ([H-02]). */\nexport const TargetLocatorV1Schema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('mediaAsset'), mediaAssetId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('hallItem'), hallItemId: z.string().min(1), subItemId: z.string().min(1).optional() }).strict(),\n z.object({ kind: z.literal('squarePost'), postId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('profileImage'), profileUid: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('username'), profileUid: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('craftSkill'), profileUid: z.string().min(1), craftSkillId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('commissionListing'), commissionListingId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('commissionProposal'), commissionListingId: z.string().min(1), commissionProposalId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('workProject'), workProjectId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('workAsset'), workProjectId: z.string().min(1), workAssetId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('workRealm'), workRealmId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('audition'), auditionId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('auditionEntry'), auditionId: z.string().min(1), auditionEntryId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('guildInviteMessage'), channelId: z.string().min(1), messageId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('chatAttachment'), channelId: z.string().min(1), messageId: z.string().min(1), attachmentId: z.string().min(1) }).strict(),\n // [H-04 V1] Plain guild chat message (text-only or Worker-unresolved). Distinct from\n // `chatAttachment` (which carries an actual attachment id) so a text-only protected chat\n // report has a clean, unambiguous locator without misusing the attachment variant.\n z.object({ kind: z.literal('guildChatMessage'), channelId: z.string().min(1), messageId: z.string().min(1) }).strict(),\n // A work-party admin correspondence message — a Firestore doc at\n // pendingAdminDispatches/{adminDispatchId}/conversationMessages/{messageId} (unlike the\n // DO-addressed guildChatMessage/guildInviteMessage locators, messageId here is a doc id,\n // not a numeric seq).\n z.object({ kind: z.literal('adminWorkMessage'), adminDispatchId: z.string().min(1), messageId: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('url'), url: z.string().min(1) }).strict(),\n z.object({ kind: z.literal('additionalText'), textRef: z.string().min(1) }).strict(),\n]);\nexport type TargetLocatorV1 = z.infer<typeof TargetLocatorV1Schema>;\n\n/** The set of locator discriminants — used wherever only the `kind` is needed. */\nexport const TargetLocatorKindSchema = z.enum([\n 'mediaAsset',\n 'hallItem',\n 'squarePost',\n 'profileImage',\n 'username',\n 'craftSkill',\n 'commissionListing',\n 'commissionProposal',\n 'workProject',\n 'workAsset',\n 'workRealm',\n 'audition',\n 'auditionEntry',\n 'guildInviteMessage',\n 'chatAttachment',\n // [H-04 V1] Plain guild chat message locator (text-only / Worker-unresolved protected report).\n 'guildChatMessage',\n // Work-party admin correspondence message (Firestore conversationMessages doc).\n 'adminWorkMessage',\n 'url',\n 'additionalText',\n]);\nexport type TargetLocatorKind = z.infer<typeof TargetLocatorKindSchema>;\n\n/** Privacy-safe summary ONLY — no narrative / PII; used on roots + public rows. */\nexport const TargetLocatorSummaryV1Schema = z.object({\n kind: TargetLocatorKindSchema,\n surfaceLabel: z.string(),\n hasResolvedTarget: z.boolean(),\n}).strict();\nexport type TargetLocatorSummaryV1 = z.infer<typeof TargetLocatorSummaryV1Schema>;\n\n// ===========================================================================\n// A9 — Reporting determination + NCMEC submission state\n// ===========================================================================\n\n/** Case-level reporting determination (Finding-H6). The ONLY carrier of \"no\n * NCMEC report required\" — `notRequired` was removed from NcmecSubmissionState. */\nexport const ReportDispositionSchema = z.enum([\n 'undetermined',\n 'reportRequired',\n 'notRequired',\n 'correctedNoApparentViolation',\n]);\nexport type ReportDisposition = z.infer<typeof ReportDispositionSchema>;\n\n/** Reason codes for the privileged setReportDisposition command (§A9). The first five are the\n * not-required / exception reasons (no NCMEC report ever arose, or a triggering signal was\n * corrected); the last two are the report-required reasons (a report IS legally required). The\n * disposition↔reason pairing is enforced by the ONE cross-field rule below (ARCH-102). */\nexport const ReportDispositionReasonCodeSchema = z.enum([\n 'outOfScopeNotCsea',\n 'basisInvalidatedFalseMatch',\n 'duplicateOfFiledReport',\n 'leDirectedNoReport',\n 'nonReportableSafetyConfirmed',\n // Report-required reasons — valid ONLY with disposition 'reportRequired'.\n 'apparentCsamConfirmed', // human review confirmed apparent CSAM\n 'hashMatchValidated', // validated hash match\n]);\nexport type ReportDispositionReasonCode = z.infer<typeof ReportDispositionReasonCodeSchema>;\n\n/** The reason codes that ASSERT a reporting obligation — legal ONLY with 'reportRequired'.\n * Compile-linked subset of the canonical reason enum. */\nexport const REPORT_REQUIRED_DISPOSITION_REASON_CODES = [\n 'apparentCsamConfirmed',\n 'hashMatchValidated',\n] as const satisfies readonly ReportDispositionReasonCode[];\n\n/** The not-required / exception reason codes — legal with every disposition that does NOT assert a\n * reporting obligation ('notRequired', 'correctedNoApparentViolation'). Compile-linked subset. */\nexport const NOT_REQUIRED_DISPOSITION_REASON_CODES = [\n 'outOfScopeNotCsea',\n 'basisInvalidatedFalseMatch',\n 'duplicateOfFiledReport',\n 'leDirectedNoReport',\n 'nonReportableSafetyConfirmed',\n] as const satisfies readonly ReportDispositionReasonCode[];\n\n/** The ONE cross-field pairing (§A9, ARCH-102): which reason codes each disposition permits.\n * Declared HERE once; both the setReportDisposition input (case.ts) and the SafetyDispositionAction\n * console command (admin.ts) apply `refineReportDispositionReasonCode` derived from this map rather\n * than re-declaring the pairing. 'undetermined' is the initial state, never an operator-settable\n * target, so it permits NO reason code (the operator command excludes it). Typed as an exhaustive\n * Record so a new disposition fails to compile until its permitted codes are declared. */\nexport const REPORT_DISPOSITION_ALLOWED_REASON_CODES: Record<\n ReportDisposition,\n readonly ReportDispositionReasonCode[]\n> = {\n undetermined: [],\n reportRequired: REPORT_REQUIRED_DISPOSITION_REASON_CODES,\n notRequired: NOT_REQUIRED_DISPOSITION_REASON_CODES,\n correctedNoApparentViolation: NOT_REQUIRED_DISPOSITION_REASON_CODES,\n};\n\n/** Shared cross-field refinement enforcing the disposition↔reason pairing above. Applied by BOTH\n * the setReportDisposition input schemas and the SafetyDispositionAction console command so the\n * rule lives in exactly one place. Reports the failure on the `dispositionReasonCode` path. */\nexport function refineReportDispositionReasonCode(\n value: { disposition: ReportDisposition; dispositionReasonCode: ReportDispositionReasonCode },\n ctx: z.RefinementCtx,\n): void {\n if (!REPORT_DISPOSITION_ALLOWED_REASON_CODES[value.disposition].includes(value.dispositionReasonCode)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['dispositionReasonCode'],\n message: `Reason code '${value.dispositionReasonCode}' is not valid for disposition '${value.disposition}'.`,\n });\n }\n}\n\n/** Shared cross-field rule (§A9): disposition 'reportRequired' MUST carry at least one evidence ref —\n * a reporting obligation can only be asserted once the evidence has been revealed. Every OTHER\n * disposition ('notRequired', 'correctedNoApparentViolation', 'undetermined') MAY leave evidenceRefs\n * empty. Declared HERE once (ARCH-102) and applied — alongside refineReportDispositionReasonCode — by\n * BOTH the setReportDisposition input schemas (case.ts) and the SafetyStagedAction console command\n * (admin.ts), never re-declared. Reports the failure on the `evidenceRefs` path. */\nexport function refineReportDispositionEvidenceRefs(\n value: { disposition: ReportDisposition; evidenceRefs: readonly string[] },\n ctx: z.RefinementCtx,\n): void {\n if (value.disposition === 'reportRequired' && value.evidenceRefs.length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['evidenceRefs'],\n message:\n \"Disposition 'reportRequired' requires at least one evidence ref (evidence must have been revealed).\",\n });\n }\n}\n\n// ===========================================================================\n// [EUAS-008] Structured safety-case CLOSURE record — the operator's terminal\n// determination persisted when a CSAM / NCII case is closed via the guided\n// resolution flow (resolveAdminTask). Embedded on the NCII case (`closure`) and on\n// a child-safety `decisions/{id}` row (kind `caseClosed`) so both case types carry\n// the SAME structured outcome/summary/note + actor/timestamp — not just a status\n// flip. This does NOT replace the case lifecycle's own terminal status; it records\n// WHO closed it, WHY, and with what outcome.\n// ===========================================================================\n\n/** founded = a violation was substantiated; unfounded = no violation on review. */\nexport const SafetyCaseClosureOutcomeSchema = z.enum(['founded', 'unfounded']);\nexport type SafetyCaseClosureOutcome = z.infer<typeof SafetyCaseClosureOutcomeSchema>;\n\n/** The structured closure record written on a safety-case close. */\nexport const SafetyCaseClosureV1Schema = z.object({\n outcome: SafetyCaseClosureOutcomeSchema,\n resolutionSummary: z.string().min(1).max(MAX_SAFETY_RESOLUTION_SUMMARY_LENGTH),\n adminNote: z.string().max(MAX_SAFETY_ADMIN_NOTE_LENGTH).optional(),\n closedByUid: z.string().min(1),\n closedAt: z.number(),\n}).strict();\nexport type SafetyCaseClosureV1 = z.infer<typeof SafetyCaseClosureV1Schema>;\n\n/** NCMEC submission lifecycle — MANUAL-PORTAL model (§A9). NO `notRequired` (that is\n * ReportDisposition). There is no automated ispws API: a report-needed obligation sits in\n * `awaitingManualFiling` from enqueue until the operator files on the NCMEC portal and records the\n * confirmation (markNcmecPortalComplete → `completed`). Jobs are born `awaitingManualFiling`; the\n * case-list `ncmecStatus` projection uses the same value (no separate `queued` state). There is no\n * in-app retraction — corrections are portal-manual (correction-lifecycle decision). The old\n * API-drive states\n * (opening/open/uploading/addingFileDetails/finishing/retryableFailure/ambiguousResult/permanentFailure)\n * were removed with the live-API client. */\nexport const NcmecSubmissionStateSchema = z.enum([\n 'awaitingManualFiling',\n 'completed',\n]);\nexport type NcmecSubmissionState = z.infer<typeof NcmecSubmissionStateSchema>;\n\n// ===========================================================================\n// A3 — Safety-hold + resource-command vocabularies (the ONE destructive-guard\n// authority). The NCII/storage resource types live in THIS enum (H1 fix).\n// ===========================================================================\n\nexport const SafetyHoldResourceTypeSchema = z.enum([\n 'contentDoc',\n 'mediaAsset',\n 'account',\n 'chatMessageRange',\n 'channel',\n 'nciiTemporaryTarget',\n 'storageObject',\n 'reportEvidenceObject',\n]);\nexport type SafetyHoldResourceType = z.infer<typeof SafetyHoldResourceTypeSchema>;\n\n/** Lifecycle/retention regime governed by the A3 compatibility matrix. */\nexport const SafetyHoldClassSchema = z.enum([\n 'childSafety',\n 'nciiTemporary',\n 'legalRetention',\n 'preservationEvidence',\n // An OPEN ordinary (non-protected) content report places an account-level hold\n // (resourceType 'account', ownerUid = the reported user) so a user can't delete\n // their data out from under an unreviewed report (e.g. a DMCA/IP complaint, then\n // delete-to-clear-tracks). blocksDeletion + blocksAnonymization; released when the\n // report group's admin close-out resolves it. Durable (no expiresAt).\n 'ordinaryReport',\n]);\nexport type SafetyHoldClass = z.infer<typeof SafetyHoldClassSchema>;\n\n/** Resource-scoped destructive command kinds (A3). */\nexport const SafetyCommandKindSchema = z.enum([\n 'nciiRemoval',\n 'csamActiveByteRemoval',\n 'evidenceDisposition',\n]);\nexport type SafetyCommandKind = z.infer<typeof SafetyCommandKindSchema>;\n\n// ===========================================================================\n// Reviewer-capability matrix (§A11 [M4] + §A9). One solo operator holds all\n// at launch; every privileged command checks the SPECIFIC capability + reauth.\n// ===========================================================================\n\nexport const SafetyReviewerCapabilitySchema = z.enum([\n 'nciiRequestReviewer',\n 'nciiEvidenceReviewer',\n 'nciiAppealReviewer',\n 'childSafetyReviewer',\n 'legalDispositionAuthority',\n]);\nexport type SafetyReviewerCapability = z.infer<typeof SafetyReviewerCapabilitySchema>;\n\n// ===========================================================================\n// A7 — Registration-completion outcome (DOMAIN enum; replaces the unsafe\n// generic gRPC retryable/terminal code lists). Only a domain outcome feeds the\n// orphan-Auth deletion policy.\n// ===========================================================================\n\nexport const RegistrationCompletionOutcomeSchema = z.enum([\n 'completed',\n 'alreadyCompletedSameUid',\n 'retryableInfrastructureFailure',\n 'reauthenticationRequired',\n 'appCheckRetryRequired',\n 'nonceExpired',\n 'nonceUnknown',\n 'nonceConsumedDifferentUid',\n 'sessionHashMismatch',\n 'attestationSignatureInvalid',\n 'privateDataConflict',\n 'policyVersionRejected',\n]);\nexport type RegistrationCompletionOutcome = z.infer<typeof RegistrationCompletionOutcomeSchema>;\n\n// ===========================================================================\n// A11 — NCII / TAKE IT DOWN shared vocabularies (consumed by BOTH NCII clusters)\n// ===========================================================================\n\n/** Closed enum of required field codes — completeness + public missing-fields. */\nexport const TakeItDownFieldCodeSchema = z.enum([\n 'requesterName',\n 'contactEmail',\n 'contactPhone',\n 'requesterRole',\n 'electronicSignature',\n 'authorityBasis',\n 'authorityCertification',\n 'authorityEvidence',\n 'targetLocator',\n 'nonconsentStatement',\n 'supportingFacts',\n 'goodFaithCertification',\n]);\nexport type TakeItDownFieldCode = z.infer<typeof TakeItDownFieldCodeSchema>;\n\n/** Closed PUBLIC-SAFE reason codes — never reveal evidence/uploader/crossover. */\nexport const TakeItDownPublicReasonCodeSchema = z.enum([\n 'needMoreInformation',\n 'couldNotVerifyRequesterRole',\n 'couldNotLocateContent',\n 'outsideCoveredScope',\n 'duplicateOfExistingRequest',\n 'removedSuccessfully',\n 'underReview',\n 'closedSeeNotice',\n]);\nexport type TakeItDownPublicReasonCode = z.infer<typeof TakeItDownPublicReasonCodeSchema>;\n\n/** Validity-failure reason codes ([H2]). `incomplete` is a COMPLETENESS state,\n * NEVER a validity state. */\nexport const TakeItDownInvalidReasonCodeSchema = z.enum([\n 'missingSignature',\n 'missingLocator',\n 'missingNonconsentStatement',\n 'missingContactInformation',\n 'requesterNotDepictedPersonOrAuthorizedRepresentative',\n 'authorityNotEstablished',\n 'locatorNotResolvableAfterReasonableEffort',\n 'requestOutsideCoveredDepiction',\n 'duplicateSuperseded',\n 'fraudulentOrBadFaith',\n 'otherCounselApproved',\n]);\nexport type TakeItDownInvalidReasonCode = z.infer<typeof TakeItDownInvalidReasonCodeSchema>;\n\n/** Requester role (depicted person vs authorized representative). */\nexport const TakeItDownRequesterRoleSchema = z.enum(['depictedPerson', 'authorizedRepresentative']);\nexport type TakeItDownRequesterRole = z.infer<typeof TakeItDownRequesterRoleSchema>;\n\n/** Two-axis state: completeness vs validity (H2). */\nexport const TakeItDownCompletenessStatusSchema = z.enum(['incomplete', 'complete']);\nexport type TakeItDownCompletenessStatus = z.infer<typeof TakeItDownCompletenessStatusSchema>;\n\nexport const TakeItDownValidityStatusSchema = z.enum(['pending', 'valid', 'invalid', 'unableToLocate']);\nexport type TakeItDownValidityStatus = z.infer<typeof TakeItDownValidityStatusSchema>;\n\n/** The public no-login status-page status set (root + statusProjection). No\n * appeal model — no `appealedCorrected` (the appeal/reinstatement flow was\n * removed; protected reports have no uploader appeal/notice/reinstatement). */\nexport const TakeItDownPublicStatusSchema = z.enum([\n 'received',\n 'needsMoreInfo',\n 'validInProgress',\n 'completed',\n 'unableToLocate',\n 'invalidGeneralReason',\n]);\nexport type TakeItDownPublicStatus = z.infer<typeof TakeItDownPublicStatusSchema>;\n\n/** Request action types ([L1]). */\nexport const NciiActionTypeSchema = z.enum([\n 'intakeReceived',\n 'completenessDecided',\n 'validityDecided',\n 'tempHoldPlaced',\n 'tempHoldReleased',\n 'removalStarted',\n 'removalCompleted',\n 'hashBlockReversed',\n 'childSafetyCaseLinked',\n 'legalDispositionRecorded',\n]);\nexport type NciiActionType = z.infer<typeof NciiActionTypeSchema>;\n\nexport const NciiActionResultSchema = z.enum(['succeeded', 'failed', 'deferred', 'rejected']);\nexport type NciiActionResult = z.infer<typeof NciiActionResultSchema>;\n\n/** Honest derived completion ([H4]) — never 'completed' for a partial failure. */\nexport const NciiRemovalCompletionOutcomeSchema = z.enum([\n 'completed',\n 'completedWithApprovedException',\n 'unableToComplete',\n]);\nexport type NciiRemovalCompletionOutcome = z.infer<typeof NciiRemovalCompletionOutcomeSchema>;\n\nexport const NciiTargetSurfaceSchema = z.enum([\n 'original',\n 'hallCopy',\n 'profileMedia',\n 'chatAttachment',\n 'variant',\n 'cacheServing',\n 'exactHashMatch',\n]);\nexport type NciiTargetSurface = z.infer<typeof NciiTargetSurfaceSchema>;\n\nexport const NciiTargetOutcomeSchema = z.enum([\n 'pending',\n 'removed',\n 'tombstoned',\n 'verifiedGone',\n 'leftoverRetrying',\n 'unableToComplete',\n 'terminalException',\n]);\nexport type NciiTargetOutcome = z.infer<typeof NciiTargetOutcomeSchema>;\n\n/** CLOSED terminal-exception enum — a technical outage is NOT an exception. */\nexport const NciiTerminalExceptionSchema = z.enum([\n 'legallyPermittedRetention',\n 'contentNotPresentVerified',\n 'counselApprovedException',\n]);\nexport type NciiTerminalException = z.infer<typeof NciiTerminalExceptionSchema>;\n\n/** Internal operational case status ([H7]).\n *\n * [R12] close-lifecycle states: clicking **Close** (after the strict-closable gate passes)\n * applies the staged actions and moves the case to `processing` — it STAYS pinned/in-queue,\n * NEVER cleared on the click. The NCII removal worker flips the case to the terminal `closed`\n * ONLY on VERIFIED removal completion (clearing the pin via onSafetyCaseClosed). If the\n * removal saga exhausts its retries (dead-letter), the case moves to `failed` — kept pinned,\n * surfaced in the Safety Console failed-jobs view, with a Restart that re-arms the job. Both\n * are explicit values (never derived). */\nexport const NciiInternalStatusSchema = z.enum([\n 'open',\n 'removalInProgress',\n 'processing',\n 'failed',\n 'removed',\n 'rejected',\n 'closed',\n]);\nexport type NciiInternalStatus = z.infer<typeof NciiInternalStatusSchema>;\n\n/** Child-safety linkage status on an NCII case ([H7]). */\nexport const NciiChildSafetyLinkStatusSchema = z.enum([\n 'none',\n 'assessmentPending',\n 'linked',\n 'resolvedNoChildSafetyCase',\n]);\nexport type NciiChildSafetyLinkStatus = z.infer<typeof NciiChildSafetyLinkStatusSchema>;\n\n// ===========================================================================\n// A11 [F4] — child-safety crossover (possible-minor ≠ automatic CSAM).\n// Embedded on nciiCases. childSafetyCaseId lives HERE (one canonical place).\n// ===========================================================================\n\nexport const NciiMinorAssessmentSchema = z.enum(['adult', 'unknown', 'possibleMinor', 'confirmedMinor']);\nexport type NciiMinorAssessment = z.infer<typeof NciiMinorAssessmentSchema>;\n\nexport const NciiCsamAssessmentSchema = z.enum([\n 'notAssessed',\n 'notApparent',\n 'apparentViolation',\n 'validatedHashMatch',\n]);\nexport type NciiCsamAssessment = z.infer<typeof NciiCsamAssessmentSchema>;\n\nexport const NciiChildSafetyCrossoverSchema = z.object({\n minorAssessment: NciiMinorAssessmentSchema,\n csamAssessment: NciiCsamAssessmentSchema,\n childSafetyCaseId: z.string().min(1).optional(),\n assessedByUid: z.string().min(1).optional(),\n assessedAt: z.number().optional(),\n}).strict();\nexport type NciiChildSafetyCrossover = z.infer<typeof NciiChildSafetyCrossoverSchema>;\n\n/** [H-2] Per-leg lifecycle status for the possible-minor crossover side-effects (serving-deny,\n * PhotoDNA) persisted on the crossover child-safety case (see ChildSafetyCaseV1.crossoverLegs).\n * `pending` is the in-transaction initial marker the assessment writes before the post-commit leg\n * runs; the leg then flips it to `done` (succeeded) or `failed` (captureException'd, awaiting a\n * reconcile/replay). A leg is ABSENT (not `pending`) when it never applied — an external / no-media\n * target has no bytes to deny or scan. */\nexport const SafetyCrossoverLegStatusSchema = z.enum(['pending', 'done', 'failed']);\nexport type SafetyCrossoverLegStatus = z.infer<typeof SafetyCrossoverLegStatusSchema>;\n"]}
@@ -2,7 +2,7 @@ import { z } from 'zod';
2
2
  import type { SquareStreetzPostType } from './social.js';
3
3
  import type { SquareStreetzPostPayload } from '../types/social.js';
4
4
  /**
5
- * The ONE canonical derivation of a Square announcement outbox job id (Rule 36
5
+ * The ONE canonical derivation of a Square announcement outbox job id (ARCH-102
6
6
  * every enqueue site, the outbox worker, and tests derive from HERE, never a
7
7
  * hand-rolled template): `${announcementType}_${primaryDocId}`, where
8
8
  * `primaryDocId` is the announcing action's natural-key doc id (e.g.
@@ -8,7 +8,7 @@
8
8
  //
9
9
  // jobId — DETERMINISTIC (collision over duplication): derived from the announcing
10
10
  // action's natural key via `buildSquareAnnouncementJobId` below — the ONE canonical
11
- // derivation (Rule 36); enqueue sites, the worker, and tests MUST call it, never
11
+ // derivation (ARCH-102); enqueue sites, the worker, and tests MUST call it, never
12
12
  // hand-roll the template. The enqueue MUST use `.create()` at this id inside the
13
13
  // announcing transaction, so a replayed/retried transaction COLLIDES with the
14
14
  // already-enqueued job instead of duplicating the announcement.
@@ -18,7 +18,7 @@
18
18
  import { z } from 'zod';
19
19
  import { SquareStreetzPostTypeSchema } from './social.js';
20
20
  /**
21
- * The ONE canonical derivation of a Square announcement outbox job id (Rule 36
21
+ * The ONE canonical derivation of a Square announcement outbox job id (ARCH-102
22
22
  * every enqueue site, the outbox worker, and tests derive from HERE, never a
23
23
  * hand-rolled template): `${announcementType}_${primaryDocId}`, where
24
24
  * `primaryDocId` is the announcing action's natural-key doc id (e.g.