@ttt-productions/ttt-core 0.78.23 → 0.78.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/app-mode.d.ts +1 -0
- package/dist/constants/app-mode.d.ts.map +1 -1
- package/dist/constants/app-mode.js +11 -0
- package/dist/constants/app-mode.js.map +1 -1
- package/dist/constants/business-user.d.ts +1 -1
- package/dist/constants/business-user.js +1 -1
- package/dist/constants/business-user.js.map +1 -1
- package/dist/constants/release-flags.d.ts +2 -2
- package/dist/constants/release-flags.d.ts.map +1 -1
- package/dist/constants/release-flags.js +2 -2
- package/dist/constants/release-flags.js.map +1 -1
- package/dist/doc-schemas/chat-sync.d.ts.map +1 -1
- package/dist/doc-schemas/chat-sync.js +3 -2
- package/dist/doc-schemas/chat-sync.js.map +1 -1
- package/dist/doc-schemas/commissions.d.ts +14 -11
- package/dist/doc-schemas/commissions.d.ts.map +1 -1
- package/dist/doc-schemas/commissions.js +14 -4
- package/dist/doc-schemas/commissions.js.map +1 -1
- package/dist/doc-schemas/media-activation-jobs.d.ts.map +1 -1
- package/dist/doc-schemas/media-activation-jobs.js +4 -3
- package/dist/doc-schemas/media-activation-jobs.js.map +1 -1
- package/dist/doc-schemas/media-assets.d.ts +2 -2
- package/dist/doc-schemas/media-assets.d.ts.map +1 -1
- package/dist/doc-schemas/media-assets.js +5 -4
- package/dist/doc-schemas/media-assets.js.map +1 -1
- package/dist/doc-schemas/messaging.d.ts.map +1 -1
- package/dist/doc-schemas/messaging.js +3 -2
- package/dist/doc-schemas/messaging.js.map +1 -1
- package/dist/doc-schemas/ncii/allegations.js +3 -3
- package/dist/doc-schemas/ncii/allegations.js.map +1 -1
- package/dist/doc-schemas/ncii/cases.d.ts.map +1 -1
- package/dist/doc-schemas/ncii/cases.js +4 -3
- package/dist/doc-schemas/ncii/cases.js.map +1 -1
- package/dist/doc-schemas/ncii/config.d.ts.map +1 -1
- package/dist/doc-schemas/ncii/config.js +4 -3
- package/dist/doc-schemas/ncii/config.js.map +1 -1
- package/dist/doc-schemas/ncii/holds.js +3 -3
- package/dist/doc-schemas/ncii/holds.js.map +1 -1
- package/dist/doc-schemas/ncii/removal.js +3 -3
- package/dist/doc-schemas/ncii/removal.js.map +1 -1
- package/dist/doc-schemas/ncii/requests.d.ts.map +1 -1
- package/dist/doc-schemas/ncii/requests.js +4 -3
- package/dist/doc-schemas/ncii/requests.js.map +1 -1
- package/dist/doc-schemas/notification-ledger.d.ts.map +1 -1
- package/dist/doc-schemas/notification-ledger.js +3 -1
- package/dist/doc-schemas/notification-ledger.js.map +1 -1
- package/dist/doc-schemas/payments.d.ts.map +1 -1
- package/dist/doc-schemas/payments.js +2 -1
- package/dist/doc-schemas/payments.js.map +1 -1
- package/dist/doc-schemas/registry.d.ts +108 -35
- package/dist/doc-schemas/registry.d.ts.map +1 -1
- package/dist/doc-schemas/registry.js +4 -0
- package/dist/doc-schemas/registry.js.map +1 -1
- package/dist/doc-schemas/safety/age.d.ts.map +1 -1
- package/dist/doc-schemas/safety/age.js +4 -3
- package/dist/doc-schemas/safety/age.js.map +1 -1
- package/dist/doc-schemas/safety/case-aliases.d.ts.map +1 -1
- package/dist/doc-schemas/safety/case-aliases.js +5 -4
- package/dist/doc-schemas/safety/case-aliases.js.map +1 -1
- package/dist/doc-schemas/safety/case.d.ts.map +1 -1
- package/dist/doc-schemas/safety/case.js +4 -3
- package/dist/doc-schemas/safety/case.js.map +1 -1
- package/dist/doc-schemas/safety/evidence.js +3 -3
- package/dist/doc-schemas/safety/evidence.js.map +1 -1
- package/dist/doc-schemas/safety/foundation.d.ts.map +1 -1
- package/dist/doc-schemas/safety/foundation.js +5 -3
- package/dist/doc-schemas/safety/foundation.js.map +1 -1
- package/dist/doc-schemas/safety/holds.d.ts.map +1 -1
- package/dist/doc-schemas/safety/holds.js +4 -3
- package/dist/doc-schemas/safety/holds.js.map +1 -1
- package/dist/doc-schemas/safety/monitors.d.ts.map +1 -1
- package/dist/doc-schemas/safety/monitors.js +5 -3
- package/dist/doc-schemas/safety/monitors.js.map +1 -1
- package/dist/doc-schemas/safety/provenance.js +3 -3
- package/dist/doc-schemas/safety/provenance.js.map +1 -1
- package/dist/doc-schemas/safety/report.d.ts.map +1 -1
- package/dist/doc-schemas/safety/report.js +4 -3
- package/dist/doc-schemas/safety/report.js.map +1 -1
- package/dist/doc-schemas/safety/sagas.js +3 -3
- package/dist/doc-schemas/safety/sagas.js.map +1 -1
- package/dist/doc-schemas/social.d.ts +130 -0
- package/dist/doc-schemas/social.d.ts.map +1 -1
- package/dist/doc-schemas/social.js +91 -2
- package/dist/doc-schemas/social.js.map +1 -1
- package/dist/doc-schemas/square-announcement-jobs.d.ts +306 -14
- package/dist/doc-schemas/square-announcement-jobs.d.ts.map +1 -1
- package/dist/doc-schemas/square-announcement-jobs.js +15 -2
- package/dist/doc-schemas/square-announcement-jobs.js.map +1 -1
- package/dist/doc-schemas/user.js +3 -3
- package/dist/doc-schemas/user.js.map +1 -1
- package/dist/doc-schemas/work-project.js +2 -2
- package/dist/doc-schemas/work-project.js.map +1 -1
- package/dist/ids/chat-ids.d.ts +3 -2
- package/dist/ids/chat-ids.d.ts.map +1 -1
- package/dist/ids/chat-ids.js +3 -2
- package/dist/ids/chat-ids.js.map +1 -1
- package/dist/media/domain-events-admin.d.ts +0 -7
- package/dist/media/domain-events-admin.d.ts.map +1 -1
- package/dist/media/domain-events-admin.js +0 -11
- package/dist/media/domain-events-admin.js.map +1 -1
- package/dist/media/domain-events.d.ts +0 -6
- package/dist/media/domain-events.d.ts.map +1 -1
- package/dist/media/domain-events.js +1 -2
- package/dist/media/domain-events.js.map +1 -1
- package/dist/media/hall-library-target-fields.js +1 -1
- package/dist/media/hall-library-target-fields.js.map +1 -1
- package/dist/media/pending-media.d.ts +0 -54
- package/dist/media/pending-media.d.ts.map +1 -1
- package/dist/media/photodna-coverage.d.ts.map +1 -1
- package/dist/media/photodna-coverage.js +5 -3
- package/dist/media/photodna-coverage.js.map +1 -1
- package/dist/paths/related-ids.js +1 -1
- package/dist/paths/related-ids.js.map +1 -1
- package/dist/safety/ncii-intake-derivations.d.ts.map +1 -1
- package/dist/safety/ncii-intake-derivations.js +4 -2
- package/dist/safety/ncii-intake-derivations.js.map +1 -1
- package/dist/safety/resource-keys.d.ts.map +1 -1
- package/dist/safety/resource-keys.js +2 -1
- package/dist/safety/resource-keys.js.map +1 -1
- package/dist/schemas/chat.js +3 -3
- package/dist/schemas/chat.js.map +1 -1
- package/dist/schemas/ncii.js +1 -1
- package/dist/schemas/ncii.js.map +1 -1
- package/dist/schemas/notification.d.ts +8 -8
- package/dist/schemas/notification.d.ts.map +1 -1
- package/dist/schemas/notification.js +17 -11
- package/dist/schemas/notification.js.map +1 -1
- package/dist/types/social.d.ts +1 -45
- package/dist/types/social.d.ts.map +1 -1
- package/dist/types/social.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foundation.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/foundation.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,8EAA8E;AAC9E,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,qEAAqE;AACrE,4EAA4E;AAC5E,oCAAoC;AACpC,EAAE;AACF,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AAC5E,wBAAwB;AAExB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,oCAAoC,EACpC,4BAA4B,GAC7B,MAAM,6BAA6B,CAAC;AAErC,8EAA8E;AAC9E,8CAA8C;AAC9C,8EAA8E;AAE9E;gFACgF;AAChF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,IAAI,CAAC;IACvC,MAAM;IACN,YAAY;IACZ,aAAa;IACb,qBAAqB;IACrB,gBAAgB;IAChB,WAAW;IACX,eAAe;IACf,uBAAuB;IACvB,sBAAsB,EAAE,oCAAoC;IAC5D,qCAAqC,EAAE,6BAA6B;IACpE,sCAAsC;IACtC,OAAO;CACR,CAAC,CAAC;AAGH,2EAA2E;AAC3E,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,sBAAsB;IACtB,qCAAqC;CACK,CAAC;AAE7C,gEAAgE;AAChE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC,CAAC;AAG3E;;qEAEqE;AACrE,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC7C,UAAU;IACV,aAAa;IACb,oBAAoB;IACpB,qBAAqB;IACrB,qBAAqB;IACrB,iBAAiB;IACjB,sBAAsB;IACtB,oBAAoB;IACpB,uFAAuF;IACvF,kFAAkF;IAClF,+EAA+E;IAC/E,oFAAoF;IACpF,uDAAuD;IACvD,oBAAoB;IACpB,mBAAmB;IACnB,4FAA4F;IAC5F,+FAA+F;IAC/F,2FAA2F;IAC3F,oGAAoG;IACpG,yCAAyC;IACzC,uBAAuB;IACvB,UAAU;IACV,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,YAAY;CACb,CAAC,CAAC;AAGH;;;oFAGoF;AACpF,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,oBAAoB;IACpB,sBAAsB;CAC0B,CAAC;AAEnD;mFACmF;AACnF,MAAM,CAAC,MAAM,+BAA+B,GAAG;IAC7C,qBAAqB;IACrB,UAAU;IACV,gBAAgB;IAChB,oBAAoB;IACpB,qBAAqB;IACrB,YAAY;IACZ,iBAAiB;IACjB,mBAAmB;IACnB,uBAAuB;IACvB,aAAa;IACb,iFAAiF;IACjF,oBAAoB;CAC4B,CAAC;AAGnD,8EAA8E;AAC9E,+EAA+E;AAC/E,mEAAmE;AACnE,8EAA8E;AAE9E;wEACwE;AACxE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAChE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACrF,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IAC1H,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IAC/E,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACrF,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACjF,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACpH,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACnG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IAC7I,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACvF,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACrH,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACnF,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACjF,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IAC1H,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACxH,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACrJ,qFAAqF;IACrF,yFAAyF;IACzF,mFAAmF;IACnF,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACtH,iEAAiE;IACjE,wFAAwF;IACxF,yFAAyF;IACzF,sBAAsB;IACtB,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IAC5H,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IACrE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;CACrF,CAAC,CAAC;AAGH,kFAAkF;AAClF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC5C,YAAY;IACZ,UAAU;IACV,YAAY;IACZ,cAAc;IACd,UAAU;IACV,YAAY;IACZ,mBAAmB;IACnB,oBAAoB;IACpB,aAAa;IACb,WAAW;IACX,WAAW;IACX,UAAU;IACV,eAAe;IACf,oBAAoB;IACpB,gBAAgB;IAChB,+FAA+F;IAC/F,kBAAkB;IAClB,gFAAgF;IAChF,kBAAkB;IAClB,KAAK;IACL,gBAAgB;CACjB,CAAC,CAAC;AAGH,mFAAmF;AACnF,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IACnD,IAAI,EAAE,uBAAuB;IAC7B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE;CAC/B,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,8EAA8E;AAC9E,wDAAwD;AACxD,8EAA8E;AAE9E;mFACmF;AACnF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC5C,cAAc;IACd,gBAAgB;IAChB,aAAa;IACb,8BAA8B;CAC/B,CAAC,CAAC;AAGH;;;0FAG0F;AAC1F,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC,IAAI,CAAC;IACtD,mBAAmB;IACnB,4BAA4B;IAC5B,wBAAwB;IACxB,oBAAoB;IACpB,8BAA8B;IAC9B,0EAA0E;IAC1E,uBAAuB,EAAE,uCAAuC;IAChE,oBAAoB,EAAE,uBAAuB;CAC9C,CAAC,CAAC;AAGH;yDACyD;AACzD,MAAM,CAAC,MAAM,wCAAwC,GAAG;IACtD,uBAAuB;IACvB,oBAAoB;CACqC,CAAC;AAE5D;kGACkG;AAClG,MAAM,CAAC,MAAM,qCAAqC,GAAG;IACnD,mBAAmB;IACnB,4BAA4B;IAC5B,wBAAwB;IACxB,oBAAoB;IACpB,8BAA8B;CAC2B,CAAC;AAE5D;;;;;0FAK0F;AAC1F,MAAM,CAAC,MAAM,uCAAuC,GAGhD;IACF,YAAY,EAAE,EAAE;IAChB,cAAc,EAAE,wCAAwC;IACxD,WAAW,EAAE,qCAAqC;IAClD,4BAA4B,EAAE,qCAAqC;CACpE,CAAC;AAEF;;+FAE+F;AAC/F,MAAM,UAAU,iCAAiC,CAC/C,KAA6F,EAC7F,GAAoB;IAEpB,IAAI,CAAC,uCAAuC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACtG,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;YAC3B,IAAI,EAAE,CAAC,uBAAuB,CAAC;YAC/B,OAAO,EAAE,gBAAgB,KAAK,CAAC,qBAAqB,mCAAmC,KAAK,CAAC,WAAW,IAAI;SAC7G,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;;;;oFAKoF;AACpF,MAAM,UAAU,mCAAmC,CACjD,KAA0E,EAC1E,GAAoB;IAEpB,IAAI,KAAK,CAAC,WAAW,KAAK,gBAAgB,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9E,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM;YAC3B,IAAI,EAAE,CAAC,cAAc,CAAC;YACtB,OAAO,EACL,qGAAqG;SACxG,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,6EAA6E;AAC7E,2EAA2E;AAC3E,mFAAmF;AACnF,mFAAmF;AACnF,iFAAiF;AACjF,mFAAmF;AACnF,6CAA6C;AAC7C,8EAA8E;AAE9E,mFAAmF;AACnF,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;AAG/E,oEAAoE;AACpE,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,OAAO,EAAE,8BAA8B;IACvC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,oCAAoC,CAAC;IAC9E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,QAAQ,EAAE;IAClE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACrB,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ;;;;;;;;4CAQ4C;AAC5C,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,IAAI,CAAC;IAC/C,sBAAsB;IACtB,WAAW;CACZ,CAAC,CAAC;AAGH,8EAA8E;AAC9E,8EAA8E;AAC9E,0EAA0E;AAC1E,8EAA8E;AAE9E,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,IAAI,CAAC;IACjD,YAAY;IACZ,YAAY;IACZ,SAAS;IACT,kBAAkB;IAClB,SAAS;IACT,qBAAqB;IACrB,eAAe;IACf,sBAAsB;CACvB,CAAC,CAAC;AAGH,0EAA0E;AAC1E,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC1C,aAAa;IACb,eAAe;IACf,gBAAgB;IAChB,sBAAsB;IACtB,+EAA+E;IAC/E,gFAAgF;IAChF,iFAAiF;IACjF,mFAAmF;IACnF,sEAAsE;IACtE,gBAAgB;CACjB,CAAC,CAAC;AAGH,sDAAsD;AACtD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC5C,aAAa;IACb,uBAAuB;IACvB,qBAAqB;CACtB,CAAC,CAAC;AAGH,8EAA8E;AAC9E,4EAA4E;AAC5E,+EAA+E;AAC/E,8EAA8E;AAE9E,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,IAAI,CAAC;IACnD,qBAAqB;IACrB,sBAAsB;IACtB,oBAAoB;IACpB,qBAAqB;IACrB,2BAA2B;CAC5B,CAAC,CAAC;AAGH,8EAA8E;AAC9E,yEAAyE;AACzE,+EAA+E;AAC/E,+BAA+B;AAC/B,8EAA8E;AAE9E,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,CAAC,IAAI,CAAC;IACxD,WAAW;IACX,yBAAyB;IACzB,gCAAgC;IAChC,0BAA0B;IAC1B,uBAAuB;IACvB,cAAc;IACd,cAAc;IACd,2BAA2B;IAC3B,qBAAqB;IACrB,6BAA6B;IAC7B,qBAAqB;IACrB,uBAAuB;CACxB,CAAC,CAAC;AAGH,8EAA8E;AAC9E,iFAAiF;AACjF,8EAA8E;AAE9E,kFAAkF;AAClF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC9C,eAAe;IACf,cAAc;IACd,cAAc;IACd,eAAe;IACf,qBAAqB;IACrB,gBAAgB;IAChB,wBAAwB;IACxB,mBAAmB;IACnB,eAAe;IACf,qBAAqB;IACrB,iBAAiB;IACjB,wBAAwB;CACzB,CAAC,CAAC;AAGH,kFAAkF;AAClF,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC,IAAI,CAAC;IACrD,qBAAqB;IACrB,6BAA6B;IAC7B,uBAAuB;IACvB,qBAAqB;IACrB,4BAA4B;IAC5B,qBAAqB;IACrB,aAAa;IACb,iBAAiB;CAClB,CAAC,CAAC;AAGH;6BAC6B;AAC7B,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC,IAAI,CAAC;IACtD,kBAAkB;IAClB,gBAAgB;IAChB,4BAA4B;IAC5B,2BAA2B;IAC3B,sDAAsD;IACtD,yBAAyB;IACzB,2CAA2C;IAC3C,gCAAgC;IAChC,qBAAqB;IACrB,sBAAsB;IACtB,sBAAsB;CACvB,CAAC,CAAC;AAGH,qEAAqE;AACrE,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,0BAA0B,CAAC,CAAC,CAAC;AAGpG,qDAAqD;AACrD,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;AAGrF,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAGxG;;+EAE+E;AAC/E,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,IAAI,CAAC;IACjD,UAAU;IACV,eAAe;IACf,iBAAiB;IACjB,WAAW;IACX,gBAAgB;IAChB,sBAAsB;CACvB,CAAC,CAAC;AAGH,mCAAmC;AACnC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,IAAI,CAAC;IACzC,gBAAgB;IAChB,qBAAqB;IACrB,iBAAiB;IACjB,gBAAgB;IAChB,kBAAkB;IAClB,gBAAgB;IAChB,kBAAkB;IAClB,mBAAmB;IACnB,uBAAuB;IACvB,0BAA0B;CAC3B,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;AAG9F,kFAAkF;AAClF,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC,IAAI,CAAC;IACvD,WAAW;IACX,gCAAgC;IAChC,kBAAkB;CACnB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC5C,UAAU;IACV,UAAU;IACV,cAAc;IACd,gBAAgB;IAChB,SAAS;IACT,cAAc;IACd,gBAAgB;CACjB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC5C,SAAS;IACT,SAAS;IACT,YAAY;IACZ,cAAc;IACd,kBAAkB;IAClB,kBAAkB;IAClB,mBAAmB;CACpB,CAAC,CAAC;AAGH,+EAA+E;AAC/E,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,IAAI,CAAC;IAChD,2BAA2B;IAC3B,2BAA2B;IAC3B,0BAA0B;CAC3B,CAAC,CAAC;AAGH;;;;;;;;0CAQ0C;AAC1C,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC7C,MAAM;IACN,mBAAmB;IACnB,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,UAAU;IACV,QAAQ;CACT,CAAC,CAAC;AAGH,0DAA0D;AAC1D,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC,IAAI,CAAC;IACpD,MAAM;IACN,mBAAmB;IACnB,QAAQ;IACR,2BAA2B;CAC5B,CAAC,CAAC;AAGH,8EAA8E;AAC9E,uEAAuE;AACvE,6EAA6E;AAC7E,8EAA8E;AAE9E,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAGzG,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC7C,aAAa;IACb,aAAa;IACb,mBAAmB;IACnB,oBAAoB;CACrB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IACrD,eAAe,EAAE,yBAAyB;IAC1C,cAAc,EAAE,wBAAwB;IACxC,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC/C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC3C,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ;;;;;0CAK0C;AAC1C,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC","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"]}
|
|
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 the frozen Trust & Safety spec\n// (Appendix A) — no invented values, no placeholders; the durable design owners\n// are ttt-prod docs/design/csam-detection-and-response.md,\n// docs/design/content-moderation-and-reporting.md, and\n// docs/design/nonconsensual-intimate-imagery-and-take-it-down.md.\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"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"holds.d.ts","sourceRoot":"","sources":["../../../src/doc-schemas/safety/holds.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"holds.d.ts","sourceRoot":"","sources":["../../../src/doc-schemas/safety/holds.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAexB,yEAAyE;AACzE,eAAO,MAAM,wBAAwB;;;EAAiC,CAAC;AACvE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E;;oCAEoC;AACpC,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAwBvB,CAAC;AACZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAUpE;0DAC0D;AAC1D,eAAO,MAAM,0BAA0B;;;;;;;;;kBAS5B,CAAC;AACZ,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAW9E;;mDAEmD;AACnD,eAAO,MAAM,gCAAgC;;;;;EAK3C,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAE1F;;kCAEkC;AAClC,eAAO,MAAM,0CAA0C;;;;;kBAW5C,CAAC;AACZ,MAAM,MAAM,oCAAoC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0CAA0C,CAAC,CAAC;AAE9G;;;uCAGuC;AACvC,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAkB/B,CAAC;AACZ,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAQpF;qFACqF;AACrF,eAAO,MAAM,8CAA8C;;;;kBAIhD,CAAC;AACZ,MAAM,MAAM,wCAAwC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8CAA8C,CAAC,CAAC;AAEtH;wEACwE;AACxE,eAAO,MAAM,sCAAsC;;;;;;;;;;kBAIxC,CAAC;AACZ,MAAM,MAAM,gCAAgC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sCAAsC,CAAC,CAAC"}
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
// `safetyHoldResources/{resourceKeyHash}` aggregate carries per-flag counters for
|
|
7
7
|
// O(1) destructive checks; and `safetyResourceCommands/{resourceKeyHash}__{commandId}`
|
|
8
8
|
// is the resource-scoped destructive command that resolves the release-before-delete
|
|
9
|
-
// race. Every shape here is transcribed verbatim from
|
|
10
|
-
//
|
|
11
|
-
//
|
|
9
|
+
// race. Every shape here is transcribed verbatim from the frozen Trust & Safety
|
|
10
|
+
// spec (Appendix A §A3) — no invented values, no placeholders; the durable design
|
|
11
|
+
// owners are ttt-prod docs/design/csam-detection-and-response.md and
|
|
12
|
+
// docs/design/nonconsensual-intimate-imagery-and-take-it-down.md.
|
|
12
13
|
//
|
|
13
14
|
// SHARED enums come from ./foundation.js (the single source for every cross-cluster
|
|
14
15
|
// enum); they are NEVER redefined here. The hold-ref/aggregate resource type uses
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"holds.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/holds.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — safety holds + resource-scoped destructive commands (Appendix\n// A §A3, Finding-H1 / [C-01] / [M-05]).\n//\n// The SINGLE destructive-guard authority: a `safetyHoldRefs/{caseId}__{resourceKeyHash}`\n// row is the only doc that ever authorizes/denies a destructive byte-op; the\n// `safetyHoldResources/{resourceKeyHash}` aggregate carries per-flag counters for\n// O(1) destructive checks; and `safetyResourceCommands/{resourceKeyHash}__{commandId}`\n// is the resource-scoped destructive command that resolves the release-before-delete\n// race. Every shape here is transcribed verbatim from docs/code_changes_needed/\n// trust-and-safety/IMPLEMENTATION_PLAN.md Appendix A §A3 — no invented values, no\n// placeholders.\n//\n// SHARED enums come from ./foundation.js (the single source for every cross-cluster\n// enum); they are NEVER redefined here. The hold-ref/aggregate resource type uses\n// SafetyHoldResourceTypeSchema (the H1 enum that carries the NCII/storage types); the\n// resource-command's `resourceType` uses TargetLocatorKindSchema (the [C-01] serving-\n// vs-evidence resource = `TargetLocatorV1['kind']`).\n//\n// Collection note: this cluster introduces three NEW Firestore collections plus two\n// overflow subcollections under `safetyResourceCommands`. 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 composite doc-id shapes are documented on\n// each schema below.\n\nimport { z } from 'zod';\nimport {\n SafetyHoldResourceTypeSchema,\n SafetyHoldClassSchema,\n SafetyCommandKindSchema,\n TargetLocatorKindSchema,\n} from './foundation.js';\n\n// ===========================================================================\n// A3 — safetyHoldRefs/{caseId}__{resourceKeyHash}\n// Mutable lifecycle row; the SINGLE destructive-guard hold authority (H1). Every\n// hold — child-safety AND NCII-temporary — is one of these refs; no other doc is\n// ever the authority. There is NO `holdSources[]` authority array.\n// ===========================================================================\n\n/** Lifecycle state of a hold ref. CAS release is on `state='active'`. */\nexport const SafetyHoldRefStateSchema = z.enum(['active', 'released']);\nexport type SafetyHoldRefState = z.infer<typeof SafetyHoldRefStateSchema>;\n\n/** `safetyHoldRefs/{caseId}__{resourceKeyHash}` — mutable lifecycle row; the SINGLE\n * destructive-guard hold authority (H1). Doc id is the deterministic composite\n * `{caseId}__{resourceKeyHash}`. */\nexport const SafetyHoldRefV1Schema = z.object({\n schemaVersion: z.literal(1),\n caseId: z.string().min(1),\n resourceType: SafetyHoldResourceTypeSchema,\n resourceId: z.string().min(1),\n resourceKeyHash: z.string().min(1),\n canonicalResourceKey: z.string().min(1),\n // [C-07] The uid that OWNS the held resource (the content uploader / account subject),\n // when one is resolvable. NOT load-bearing for the destructive guard (that reads ONLY\n // the resourceKeyHash aggregate) — this is an admin-observability index so active holds\n // can be listed per account (\"does this account have pending safety actions?\"). Optional:\n // some resources have no single owning uid, and the `account` key already encodes the uid.\n ownerUid: z.string().min(1).optional(),\n blocksDeletion: z.boolean(),\n blocksAnonymization: z.boolean(),\n blocksReplacementCleanup: z.boolean(),\n state: SafetyHoldRefStateSchema,\n holdClass: SafetyHoldClassSchema, // lifecycle/retention regime; FULL set governed by the A3 compatibility matrix\n createdAt: z.number(),\n releasedAt: z.number().optional(),\n releaseReason: z.string().optional(),\n sourceRequestId: z.string().min(1).optional(), // the statutory request that created an nciiTemporary hold (H1)\n expiresAt: z.number().optional(), // minimize-retention expiry for nciiTemporary holds; ABSENT for childSafety / legalRetention / preservationEvidence\n releaseCommandId: z.string().min(1).optional(), // deterministic id of the CAS release/consume command (H1)\n}).strict();\nexport type SafetyHoldRefV1 = z.infer<typeof SafetyHoldRefV1Schema>;\n\n// ===========================================================================\n// A3 — safetyHoldResources/{resourceKeyHash}\n// Aggregate for O(1) destructive checks; per-flag counters. Create-ref +\n// increment in ONE tx; release decrements the exact ref's counters in the same\n// CAS transaction. Counters never go below zero. A destructive op is denied when\n// its relevant count > 0 and FAILS CLOSED on lookup error.\n// ===========================================================================\n\n/** `safetyHoldResources/{resourceKeyHash}` — aggregate per-flag counters for O(1)\n * destructive checks. Doc id is the `resourceKeyHash`. */\nexport const SafetyHoldResourceV1Schema = z.object({\n schemaVersion: z.literal(1),\n resourceKeyHash: z.string().min(1),\n canonicalResourceKey: z.string().min(1),\n activeRefCount: z.number(),\n blocksDeletionCount: z.number(),\n blocksAnonymizationCount: z.number(),\n blocksReplacementCleanupCount: z.number(),\n updatedAt: z.number(),\n}).strict();\nexport type SafetyHoldResourceV1 = z.infer<typeof SafetyHoldResourceV1Schema>;\n\n// ===========================================================================\n// A3 — safetyResourceCommands/{resourceKeyHash}__{commandId}\n// Resource-scoped destructive command (the release-before-delete race fix).\n// `commandId` is deterministic per `(resourceKeyHash, commandKind)`, so every\n// compatible ref over the SAME bytes joins ONE command. Inline caps:\n// authorizedFor.requestIds MAX 64, bypassHoldRefIds MAX 256; overflow moves to the\n// child collections below and flips the matching `*Overflowed` flag.\n// ===========================================================================\n\n/** Command lifecycle state. The destructive byte-op runs ONLY under a command in\n * `authorized`/`executing`; a `failed` delete keeps the command + refs active for\n * idempotent retry (failed → re-lease → retry). */\nexport const SafetyResourceCommandStateSchema = z.enum([\n 'authorized',\n 'executing',\n 'verifiedRemoved',\n 'failed',\n]);\nexport type SafetyResourceCommandState = z.infer<typeof SafetyResourceCommandStateSchema>;\n\n/** The obligation(s) that authorized this destructive op. Overflow beyond\n * `requestIds` MAX 64 moves to the `authorizedRequests` child collection and sets\n * `requestIdsOverflowed=true`. */\nexport const SafetyResourceCommandAuthorizedForV1Schema = z.object({\n requestIds: z.array(z.string().min(1)).max(64),\n caseId: z.string().min(1).optional(),\n /** Additional case ids this command is authorized to bypass SERVING holds for — the\n * LINKED child-safety case(s) in an NCII↔child-safety crossover (C-08). An\n * `nciiRemoval` command authorized for the NCII `caseId` may bypass the linked\n * child-safety case's hold on the SERVING resource so the 48h removal isn't stalled;\n * the evidence-vault preservation hold has a DISTINCT resource key and is never\n * bypassable. Bounded — a crossover links at most a handful of cases. */\n linkedCaseIds: z.array(z.string().min(1)).max(32).optional(),\n requestIdsOverflowed: z.boolean().optional(),\n}).strict();\nexport type SafetyResourceCommandAuthorizedForV1 = z.infer<typeof SafetyResourceCommandAuthorizedForV1Schema>;\n\n/** `safetyResourceCommands/{resourceKeyHash}__{commandId}` — resource-scoped\n * destructive command. Doc id is the deterministic composite\n * `{resourceKeyHash}__{commandId}` where `commandId` is deterministic per\n * `(resourceKeyHash, commandKind)`. */\nexport const SafetyResourceCommandV1Schema = z.object({\n schemaVersion: z.literal(1),\n resourceKeyHash: z.string().min(1),\n canonicalResourceKey: z.string().min(1),\n commandId: z.string().min(1), // deterministic per (resourceKeyHash, commandKind)\n commandKind: SafetyCommandKindSchema,\n resourceType: TargetLocatorKindSchema, // [C-01] the SERVING vs evidence-vault resource this command targets\n authorizedFor: SafetyResourceCommandAuthorizedForV1Schema, // overflow → authorizedRequests child collection\n bypassHoldRefIds: z.array(z.string().min(1)).max(256), // ONLY the bypassable refs per the compatibility matrix; overflow → bypassRefs child collection\n bypassHoldRefsOverflowed: z.boolean().optional(),\n state: SafetyResourceCommandStateSchema,\n attemptCount: 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 verifiedRemovedAt: z.number().optional(),\n}).strict();\nexport type SafetyResourceCommandV1 = z.infer<typeof SafetyResourceCommandV1Schema>;\n\n// ===========================================================================\n// A3 [M-05] — overflow child collections under a resource command (mirror the\n// `relatedAssets` overflow pattern). A `*Overflowed` flag means the inline array\n// is NOT the complete set and the child collection MUST be consulted.\n// ===========================================================================\n\n/** `safetyResourceCommands/{resourceKeyHash}__{commandId}/authorizedRequests/{requestId}`\n * — overflow beyond `authorizedFor.requestIds` MAX 64. Doc id is the `requestId`. */\nexport const SafetyResourceCommandAuthorizedRequestV1Schema = z.object({\n requestId: z.string().min(1),\n caseId: z.string().min(1).optional(),\n addedAt: z.number(),\n}).strict();\nexport type SafetyResourceCommandAuthorizedRequestV1 = z.infer<typeof SafetyResourceCommandAuthorizedRequestV1Schema>;\n\n/** `safetyResourceCommands/{resourceKeyHash}__{commandId}/bypassRefs/{refId}` —\n * overflow beyond `bypassHoldRefIds` MAX 256. Doc id is the `refId`. */\nexport const SafetyResourceCommandBypassRefV1Schema = z.object({\n refId: z.string().min(1),\n holdClass: SafetyHoldClassSchema,\n addedAt: z.number(),\n}).strict();\nexport type SafetyResourceCommandBypassRefV1 = z.infer<typeof SafetyResourceCommandBypassRefV1Schema>;\n"]}
|
|
1
|
+
{"version":3,"file":"holds.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/holds.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — safety holds + resource-scoped destructive commands (Appendix\n// A §A3, Finding-H1 / [C-01] / [M-05]).\n//\n// The SINGLE destructive-guard authority: a `safetyHoldRefs/{caseId}__{resourceKeyHash}`\n// row is the only doc that ever authorizes/denies a destructive byte-op; the\n// `safetyHoldResources/{resourceKeyHash}` aggregate carries per-flag counters for\n// O(1) destructive checks; and `safetyResourceCommands/{resourceKeyHash}__{commandId}`\n// is the resource-scoped destructive command that resolves the release-before-delete\n// race. Every shape here is transcribed verbatim from the frozen Trust & Safety\n// spec (Appendix A §A3) — no invented values, no placeholders; the durable design\n// owners are ttt-prod docs/design/csam-detection-and-response.md and\n// docs/design/nonconsensual-intimate-imagery-and-take-it-down.md.\n//\n// SHARED enums come from ./foundation.js (the single source for every cross-cluster\n// enum); they are NEVER redefined here. The hold-ref/aggregate resource type uses\n// SafetyHoldResourceTypeSchema (the H1 enum that carries the NCII/storage types); the\n// resource-command's `resourceType` uses TargetLocatorKindSchema (the [C-01] serving-\n// vs-evidence resource = `TargetLocatorV1['kind']`).\n//\n// Collection note: this cluster introduces three NEW Firestore collections plus two\n// overflow subcollections under `safetyResourceCommands`. 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 composite doc-id shapes are documented on\n// each schema below.\n\nimport { z } from 'zod';\nimport {\n SafetyHoldResourceTypeSchema,\n SafetyHoldClassSchema,\n SafetyCommandKindSchema,\n TargetLocatorKindSchema,\n} from './foundation.js';\n\n// ===========================================================================\n// A3 — safetyHoldRefs/{caseId}__{resourceKeyHash}\n// Mutable lifecycle row; the SINGLE destructive-guard hold authority (H1). Every\n// hold — child-safety AND NCII-temporary — is one of these refs; no other doc is\n// ever the authority. There is NO `holdSources[]` authority array.\n// ===========================================================================\n\n/** Lifecycle state of a hold ref. CAS release is on `state='active'`. */\nexport const SafetyHoldRefStateSchema = z.enum(['active', 'released']);\nexport type SafetyHoldRefState = z.infer<typeof SafetyHoldRefStateSchema>;\n\n/** `safetyHoldRefs/{caseId}__{resourceKeyHash}` — mutable lifecycle row; the SINGLE\n * destructive-guard hold authority (H1). Doc id is the deterministic composite\n * `{caseId}__{resourceKeyHash}`. */\nexport const SafetyHoldRefV1Schema = z.object({\n schemaVersion: z.literal(1),\n caseId: z.string().min(1),\n resourceType: SafetyHoldResourceTypeSchema,\n resourceId: z.string().min(1),\n resourceKeyHash: z.string().min(1),\n canonicalResourceKey: z.string().min(1),\n // [C-07] The uid that OWNS the held resource (the content uploader / account subject),\n // when one is resolvable. NOT load-bearing for the destructive guard (that reads ONLY\n // the resourceKeyHash aggregate) — this is an admin-observability index so active holds\n // can be listed per account (\"does this account have pending safety actions?\"). Optional:\n // some resources have no single owning uid, and the `account` key already encodes the uid.\n ownerUid: z.string().min(1).optional(),\n blocksDeletion: z.boolean(),\n blocksAnonymization: z.boolean(),\n blocksReplacementCleanup: z.boolean(),\n state: SafetyHoldRefStateSchema,\n holdClass: SafetyHoldClassSchema, // lifecycle/retention regime; FULL set governed by the A3 compatibility matrix\n createdAt: z.number(),\n releasedAt: z.number().optional(),\n releaseReason: z.string().optional(),\n sourceRequestId: z.string().min(1).optional(), // the statutory request that created an nciiTemporary hold (H1)\n expiresAt: z.number().optional(), // minimize-retention expiry for nciiTemporary holds; ABSENT for childSafety / legalRetention / preservationEvidence\n releaseCommandId: z.string().min(1).optional(), // deterministic id of the CAS release/consume command (H1)\n}).strict();\nexport type SafetyHoldRefV1 = z.infer<typeof SafetyHoldRefV1Schema>;\n\n// ===========================================================================\n// A3 — safetyHoldResources/{resourceKeyHash}\n// Aggregate for O(1) destructive checks; per-flag counters. Create-ref +\n// increment in ONE tx; release decrements the exact ref's counters in the same\n// CAS transaction. Counters never go below zero. A destructive op is denied when\n// its relevant count > 0 and FAILS CLOSED on lookup error.\n// ===========================================================================\n\n/** `safetyHoldResources/{resourceKeyHash}` — aggregate per-flag counters for O(1)\n * destructive checks. Doc id is the `resourceKeyHash`. */\nexport const SafetyHoldResourceV1Schema = z.object({\n schemaVersion: z.literal(1),\n resourceKeyHash: z.string().min(1),\n canonicalResourceKey: z.string().min(1),\n activeRefCount: z.number(),\n blocksDeletionCount: z.number(),\n blocksAnonymizationCount: z.number(),\n blocksReplacementCleanupCount: z.number(),\n updatedAt: z.number(),\n}).strict();\nexport type SafetyHoldResourceV1 = z.infer<typeof SafetyHoldResourceV1Schema>;\n\n// ===========================================================================\n// A3 — safetyResourceCommands/{resourceKeyHash}__{commandId}\n// Resource-scoped destructive command (the release-before-delete race fix).\n// `commandId` is deterministic per `(resourceKeyHash, commandKind)`, so every\n// compatible ref over the SAME bytes joins ONE command. Inline caps:\n// authorizedFor.requestIds MAX 64, bypassHoldRefIds MAX 256; overflow moves to the\n// child collections below and flips the matching `*Overflowed` flag.\n// ===========================================================================\n\n/** Command lifecycle state. The destructive byte-op runs ONLY under a command in\n * `authorized`/`executing`; a `failed` delete keeps the command + refs active for\n * idempotent retry (failed → re-lease → retry). */\nexport const SafetyResourceCommandStateSchema = z.enum([\n 'authorized',\n 'executing',\n 'verifiedRemoved',\n 'failed',\n]);\nexport type SafetyResourceCommandState = z.infer<typeof SafetyResourceCommandStateSchema>;\n\n/** The obligation(s) that authorized this destructive op. Overflow beyond\n * `requestIds` MAX 64 moves to the `authorizedRequests` child collection and sets\n * `requestIdsOverflowed=true`. */\nexport const SafetyResourceCommandAuthorizedForV1Schema = z.object({\n requestIds: z.array(z.string().min(1)).max(64),\n caseId: z.string().min(1).optional(),\n /** Additional case ids this command is authorized to bypass SERVING holds for — the\n * LINKED child-safety case(s) in an NCII↔child-safety crossover (C-08). An\n * `nciiRemoval` command authorized for the NCII `caseId` may bypass the linked\n * child-safety case's hold on the SERVING resource so the 48h removal isn't stalled;\n * the evidence-vault preservation hold has a DISTINCT resource key and is never\n * bypassable. Bounded — a crossover links at most a handful of cases. */\n linkedCaseIds: z.array(z.string().min(1)).max(32).optional(),\n requestIdsOverflowed: z.boolean().optional(),\n}).strict();\nexport type SafetyResourceCommandAuthorizedForV1 = z.infer<typeof SafetyResourceCommandAuthorizedForV1Schema>;\n\n/** `safetyResourceCommands/{resourceKeyHash}__{commandId}` — resource-scoped\n * destructive command. Doc id is the deterministic composite\n * `{resourceKeyHash}__{commandId}` where `commandId` is deterministic per\n * `(resourceKeyHash, commandKind)`. */\nexport const SafetyResourceCommandV1Schema = z.object({\n schemaVersion: z.literal(1),\n resourceKeyHash: z.string().min(1),\n canonicalResourceKey: z.string().min(1),\n commandId: z.string().min(1), // deterministic per (resourceKeyHash, commandKind)\n commandKind: SafetyCommandKindSchema,\n resourceType: TargetLocatorKindSchema, // [C-01] the SERVING vs evidence-vault resource this command targets\n authorizedFor: SafetyResourceCommandAuthorizedForV1Schema, // overflow → authorizedRequests child collection\n bypassHoldRefIds: z.array(z.string().min(1)).max(256), // ONLY the bypassable refs per the compatibility matrix; overflow → bypassRefs child collection\n bypassHoldRefsOverflowed: z.boolean().optional(),\n state: SafetyResourceCommandStateSchema,\n attemptCount: 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 verifiedRemovedAt: z.number().optional(),\n}).strict();\nexport type SafetyResourceCommandV1 = z.infer<typeof SafetyResourceCommandV1Schema>;\n\n// ===========================================================================\n// A3 [M-05] — overflow child collections under a resource command (mirror the\n// `relatedAssets` overflow pattern). A `*Overflowed` flag means the inline array\n// is NOT the complete set and the child collection MUST be consulted.\n// ===========================================================================\n\n/** `safetyResourceCommands/{resourceKeyHash}__{commandId}/authorizedRequests/{requestId}`\n * — overflow beyond `authorizedFor.requestIds` MAX 64. Doc id is the `requestId`. */\nexport const SafetyResourceCommandAuthorizedRequestV1Schema = z.object({\n requestId: z.string().min(1),\n caseId: z.string().min(1).optional(),\n addedAt: z.number(),\n}).strict();\nexport type SafetyResourceCommandAuthorizedRequestV1 = z.infer<typeof SafetyResourceCommandAuthorizedRequestV1Schema>;\n\n/** `safetyResourceCommands/{resourceKeyHash}__{commandId}/bypassRefs/{refId}` —\n * overflow beyond `bypassHoldRefIds` MAX 256. Doc id is the `refId`. */\nexport const SafetyResourceCommandBypassRefV1Schema = z.object({\n refId: z.string().min(1),\n holdClass: SafetyHoldClassSchema,\n addedAt: z.number(),\n}).strict();\nexport type SafetyResourceCommandBypassRefV1 = z.infer<typeof SafetyResourceCommandBypassRefV1Schema>;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitors.d.ts","sourceRoot":"","sources":["../../../src/doc-schemas/safety/monitors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"monitors.d.ts","sourceRoot":"","sources":["../../../src/doc-schemas/safety/monitors.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB;;;;;yCAKyC;AACzC,eAAO,MAAM,0BAA0B;;;;;;;;;EASrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E;2BAC2B;AAC3B,eAAO,MAAM,2BAA2B;;;EAAqC,CAAC;AAC9E,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,gCAAgC;AAChC,eAAO,MAAM,4BAA4B;;;;EAA2C,CAAC;AACrF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF;;;;;yEAKyE;AACzE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAc1B,CAAC;AACZ,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAU1E,eAAO,MAAM,8BAA8B;;;;kBAIhC,CAAC;AACZ,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC"}
|
|
@@ -10,9 +10,11 @@
|
|
|
10
10
|
// and `requestId?` both optional). Arming or resolving one row MUST NOT read or
|
|
11
11
|
// write another row (no cross-monitor coupling).
|
|
12
12
|
//
|
|
13
|
-
// Every shape here is transcribed verbatim from
|
|
14
|
-
//
|
|
15
|
-
//
|
|
13
|
+
// Every shape here is transcribed verbatim from the frozen Trust & Safety spec
|
|
14
|
+
// (Appendix A §A8) — no invented values, no placeholders; the durable design owners
|
|
15
|
+
// are ttt-prod docs/design/csam-detection-and-response.md and (for the [H4]
|
|
16
|
+
// request-scoped removal deadline)
|
|
17
|
+
// docs/design/nonconsensual-intimate-imagery-and-take-it-down.md.
|
|
16
18
|
//
|
|
17
19
|
// No cross-cluster foundation enums are consumed here; the monitor enums are
|
|
18
20
|
// §A8-specific value sets and live in this file.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitors.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/monitors.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,0DAA0D;AAC1D,EAAE;AACF,kFAAkF;AAClF,uFAAuF;AACvF,0DAA0D;AAC1D,+EAA+E;AAC/E,6EAA6E;AAC7E,iFAAiF;AACjF,gFAAgF;AAChF,iDAAiD;AACjD,EAAE;AACF,
|
|
1
|
+
{"version":3,"file":"monitors.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/monitors.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,0DAA0D;AAC1D,EAAE;AACF,kFAAkF;AAClF,uFAAuF;AACvF,0DAA0D;AAC1D,+EAA+E;AAC/E,6EAA6E;AAC7E,iFAAiF;AACjF,gFAAgF;AAChF,iDAAiD;AACjD,EAAE;AACF,+EAA+E;AAC/E,oFAAoF;AACpF,4EAA4E;AAC5E,mCAAmC;AACnC,kEAAkE;AAClE,EAAE;AACF,6EAA6E;AAC7E,iDAAiD;AACjD,EAAE;AACF,wEAAwE;AACxE,uEAAuE;AACvE,gFAAgF;AAChF,+EAA+E;AAC/E,kFAAkF;AAClF,qBAAqB;AAErB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8EAA8E;AAC9E,iDAAiD;AACjD,yFAAyF;AACzF,4EAA4E;AAC5E,mCAAmC;AACnC,8EAA8E;AAE9E;;;;;yCAKyC;AACzC,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,IAAI,CAAC;IAC/C,WAAW;IACX,kBAAkB;IAClB,2BAA2B;IAC3B,YAAY;IACZ,iBAAiB;IACjB,eAAe;IACf,sBAAsB;IACtB,qBAAqB;CACtB,CAAC,CAAC;AAGH;2BAC2B;AAC3B,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;AAG9E,gCAAgC;AAChC,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;AAGrF;;;;;yEAKyE;AACzE,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,mDAAmD;IAC5F,WAAW,EAAE,0BAA0B;IACvC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE;IAC3B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,YAAY,EAAE,2BAA2B,CAAC,QAAQ,EAAE,EAAE,gCAAgC;IACtF,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,gFAAgF;IACjI,MAAM,EAAE,4BAA4B;IACpC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,8EAA8E;AAC9E,0EAA0E;AAC1E,qEAAqE;AACrE,kFAAkF;AAClF,gFAAgF;AAChF,oCAAoC;AACpC,8EAA8E;AAE9E,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IACrD,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE;CAC/B,CAAC,CAAC,MAAM,EAAE,CAAC","sourcesContent":["// Trust & Safety — per-obligation SLA monitors + the global dead-man heartbeat\n// (Appendix A §A8, Finding-M1 / Finding-H4 / Finding-H2).\n//\n// One monitor ROW per distinct obligation (the single `safetySlaMonitor/{caseId}`\n// is removed). Most rows are case-scoped — `safetySlaMonitors/{caseId}__{monitorKind}`\n// — but the NCII removal deadline is REQUEST-scoped [H4]:\n// `safetySlaMonitors/{requestId}__nciiRemovalDeadline`, because each statutory\n// request owns its own 48h obligation and a monitor can never be resolved by\n// finishing a DIFFERENT linked request. ONE schema covers both shapes (`caseId?`\n// and `requestId?` both optional). Arming or resolving one row MUST NOT read or\n// write another row (no cross-monitor coupling).\n//\n// Every shape here is transcribed verbatim from the frozen Trust & Safety spec\n// (Appendix A §A8) — no invented values, no placeholders; the durable design owners\n// are ttt-prod docs/design/csam-detection-and-response.md and (for the [H4]\n// request-scoped removal deadline)\n// docs/design/nonconsensual-intimate-imagery-and-take-it-down.md.\n//\n// No cross-cluster foundation enums are consumed here; the monitor enums are\n// §A8-specific value sets and live in this file.\n//\n// Collection note: this cluster introduces ONE NEW Firestore collection\n// (`safetySlaMonitors`, two doc-id shapes) plus ONE singleton document\n// (`safetyMonitorHeartbeat/global`). Wiring collections.ts / path-builders.ts /\n// registry.ts is deferred to the app leg (the orchestrator binds the schemas +\n// path builders there); the composite + singleton doc-id shapes are documented on\n// each schema below.\n\nimport { z } from 'zod';\n\n// ===========================================================================\n// A8 — safetySlaMonitors/{caseId}__{monitorKind}\n// AND the request-scoped variant safetySlaMonitors/{requestId}__nciiRemovalDeadline\n// One row per distinct obligation. Each fires the external (Sentry / Cloud-\n// Monitoring) alarm independently.\n// ===========================================================================\n\n/** The distinct obligation kinds. The two FIXED (non-operator-configurable)\n * headline urgent-tab countdowns are `photoDnaContract` (the CSAM 72h match-\n * reporting clock) and `nciiRemovalDeadline` (the NCII 48h statutory removal\n * clock). The rest are internal operational alarms on a CSAM/NCII case, never the\n * headline clock. Clocks + the urgent tab attach ONLY to PhotoDNA-hash detections\n * and cases reported as CSAM or NCII. */\nexport const SafetySlaMonitorKindSchema = z.enum([\n 'reviewDue',\n 'photoDnaContract',\n 'actualKnowledgeUnreported',\n 'ncmecRetry',\n 'quarantineStall',\n 'evidenceStall',\n 'accountActionPending',\n 'nciiRemovalDeadline',\n]);\nexport type SafetySlaMonitorKind = z.infer<typeof SafetySlaMonitorKindSchema>;\n\n/** [H2] nciiRemovalDeadline only: `provisional` on first facial-completeness,\n * `binding` once valid. */\nexport const SafetySlaMonitorStageSchema = z.enum(['provisional', 'binding']);\nexport type SafetySlaMonitorStage = z.infer<typeof SafetySlaMonitorStageSchema>;\n\n/** Monitor lifecycle status. */\nexport const SafetySlaMonitorStatusSchema = z.enum(['armed', 'overdue', 'resolved']);\nexport type SafetySlaMonitorStatus = z.infer<typeof SafetySlaMonitorStatusSchema>;\n\n/** `safetySlaMonitors/{caseId}__{monitorKind}` — per-obligation SLA monitor.\n * The `nciiRemovalDeadline` row is REQUEST-scoped [H4]: its doc id is the\n * composite `{requestId}__nciiRemovalDeadline` and it carries `requestId` (not\n * `caseId`). ONE schema covers both shapes — `caseId?` and `requestId?` are both\n * optional. The case `nciiCases/{caseId}.nciiRemovalDeadlineAt` is a\n * NON-authoritative projection of the minimum active request monitor. */\nexport const SafetySlaMonitorV1Schema = z.object({\n schemaVersion: z.literal(1),\n caseId: z.string().min(1).optional(),\n requestId: z.string().min(1).optional(), // nciiRemovalDeadline rows are request-scoped [H4]\n monitorKind: SafetySlaMonitorKindSchema,\n armedAt: z.number(),\n deadlineAt: z.number(),\n escalationLevel: z.number(),\n lastFiredAt: z.number().optional(),\n monitorStage: SafetySlaMonitorStageSchema.optional(), // [H2] nciiRemovalDeadline only\n basisSubmissionId: z.string().min(1).optional(), // [H2] the immutable TakeItDownSubmissionV1 whose receivedAt pins this deadline\n status: SafetySlaMonitorStatusSchema,\n resolvedAt: z.number().optional(),\n resolutionBasis: z.string().optional(),\n}).strict();\nexport type SafetySlaMonitorV1 = z.infer<typeof SafetySlaMonitorV1Schema>;\n\n// ===========================================================================\n// A8 — safetyMonitorHeartbeat/global (global dead-man monitor; SINGLETON)\n// The scheduled monitor sweep stamps `lastRunAt`; a missed heartbeat\n// (now − lastRunAt > expectedIntervalMs) self-alarms out-of-band. Removes the old\n// per-case `heartbeatAt` — the heartbeat is GLOBAL, not per-case. Doc id is the\n// fixed singleton literal `global`.\n// ===========================================================================\n\nexport const SafetyMonitorHeartbeatV1Schema = z.object({\n schemaVersion: z.literal(1),\n lastRunAt: z.number(),\n expectedIntervalMs: z.number(),\n}).strict();\nexport type SafetyMonitorHeartbeatV1 = z.infer<typeof SafetyMonitorHeartbeatV1Schema>;\n"]}
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
// the evidence manifest (retentionClass='casePromoted', hold-governed). A scheduled
|
|
7
7
|
// deletion worker enforces the routine TTLs with a hold-aware no-delete guard.
|
|
8
8
|
//
|
|
9
|
-
// Every shape here is transcribed verbatim from
|
|
10
|
-
//
|
|
11
|
-
//
|
|
9
|
+
// Every shape here is transcribed verbatim from the frozen Trust & Safety spec
|
|
10
|
+
// (Appendix A §A6) — no invented values, no placeholders; the durable design owner
|
|
11
|
+
// is ttt-prod docs/design/safety-evidence-control-profile.md.
|
|
12
12
|
//
|
|
13
13
|
// Collection note: this cluster introduces ONE NEW Firestore collection. Wiring
|
|
14
14
|
// collections.ts / path-builders.ts / registry.ts is deferred to the app leg (the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provenance.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/provenance.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,sBAAsB;AACtB,EAAE;AACF,8EAA8E;AAC9E,mFAAmF;AACnF,oFAAoF;AACpF,+EAA+E;AAC/E,EAAE;AACF
|
|
1
|
+
{"version":3,"file":"provenance.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/provenance.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,sBAAsB;AACtB,EAAE;AACF,8EAA8E;AAC9E,mFAAmF;AACnF,oFAAoF;AACpF,+EAA+E;AAC/E,EAAE;AACF,+EAA+E;AAC/E,mFAAmF;AACnF,8DAA8D;AAC9D,EAAE;AACF,gFAAgF;AAChF,kFAAkF;AAClF,gFAAgF;AAChF,2CAA2C;AAE3C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8EAA8E;AAC9E,kCAAkC;AAClC,6EAA6E;AAC7E,+EAA+E;AAC/E,yEAAyE;AACzE,8EAA8E;AAE9E,6BAA6B;AAC7B,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC9C,YAAY;IACZ,gBAAgB;IAChB,aAAa;IACb,OAAO;IACP,cAAc;CACf,CAAC,CAAC;AAGH;;;;;;8EAM8E;AAC9E,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC;AAGvF;8CAC8C;AAC9C,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC,MAAM,CAAC;IACvD,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACjC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACrC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACvC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ;;;8EAG8E;AAC9E,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3B,IAAI,EAAE,yBAAyB;IAC/B,WAAW,EAAE,gCAAgC,EAAE,kCAAkC;IACjF,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,qEAAqE;IAClG,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,qCAAqC;IACrE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,cAAc,EAAE,mCAAmC;CACpD,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,8EAA8E;AAC9E,mFAAmF;AACnF,+EAA+E;AAC/E,8CAA8C;AAC9C,8EAA8E;AAE9E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,iCAAiC,GAAG;IAC/C,UAAU,EAAE,EAAE;IACd,cAAc,EAAE,EAAE;IAClB,WAAW,EAAE,EAAE;IACf,KAAK,EAAE,EAAE;IACT,yDAAyD;CACjD,CAAC","sourcesContent":["// Trust & Safety — the provenance cluster (Appendix A §A6, Finding-M2 concrete\n// retention profile).\n//\n// `eventProvenance/{eventId}` — server-only, restricted provenance for source\n// events (upload/message/login/report). On a hold the record is copied/linked into\n// the evidence manifest (retentionClass='casePromoted', hold-governed). A scheduled\n// deletion worker enforces the routine TTLs with a hold-aware no-delete guard.\n//\n// Every shape here is transcribed verbatim from the frozen Trust & Safety spec\n// (Appendix A §A6) — no invented values, no placeholders; the durable design owner\n// is ttt-prod docs/design/safety-evidence-control-profile.md.\n//\n// Collection note: this cluster introduces ONE NEW Firestore collection. Wiring\n// collections.ts / path-builders.ts / registry.ts is deferred to the app leg (the\n// orchestrator binds the schema + path builder there); the deterministic doc-id\n// shape is documented on the schema below.\n\nimport { z } from 'zod';\n\n// ===========================================================================\n// §A6 — eventProvenance/{eventId}\n// `eventId` is DETERMINISTIC per source event (e.g. the upload event id, the\n// message-send seq key, the login session key, or the report id) so a replayed\n// source event converges on the same provenance doc — never a duplicate.\n// ===========================================================================\n\n/** §A6 source-event kind. */\nexport const EventProvenanceKindSchema = z.enum([\n 'uploadInit',\n 'uploadFinalize',\n 'messageSend',\n 'login',\n 'reportSubmit',\n]);\nexport type EventProvenanceKind = z.infer<typeof EventProvenanceKindSchema>;\n\n/** §A6 retention class. Build defaults (counsel may only SHORTEN):\n * routine uploadInit/uploadFinalize/messageSend = 90 days;\n * login = 30 days;\n * reportSubmit = retained with the case.\n * On a hold the record is copied/linked into the evidence manifest as\n * 'casePromoted' (hold-governed); the scheduled deletion worker's hold-aware\n * no-delete guard never deletes a casePromoted record while a hold exists. */\nexport const EventProvenanceRetentionClassSchema = z.enum(['routine', 'casePromoted']);\nexport type EventProvenanceRetentionClass = z.infer<typeof EventProvenanceRetentionClassSchema>;\n\n/** §A6 `subjectRefs` — a TYPED object, NOT an open array. Each field is the\n * relevant id for the source event's kind. */\nexport const EventProvenanceSubjectRefsSchema = z.object({\n uid: z.string().min(1).optional(),\n assetId: z.string().min(1).optional(),\n channelId: z.string().min(1).optional(),\n messageSeq: z.number().optional(),\n reportId: z.string().min(1).optional(),\n}).strict();\nexport type EventProvenanceSubjectRefs = z.infer<typeof EventProvenanceSubjectRefsSchema>;\n\n/** `eventProvenance/{eventId}` — server-only, restricted provenance row. Doc id is\n * deterministic per source event. `trustedClientIp` is derived behind Firebase/\n * Cloudflare and is a restricted, INDEX-EXEMPT field; `userAgent` is truncated to\n * 256 chars + normalized. NO reuse for ads/engagement-profiling/analytics. */\nexport const EventProvenanceV1Schema = z.object({\n schemaVersion: z.literal(1),\n kind: EventProvenanceKindSchema,\n subjectRefs: EventProvenanceSubjectRefsSchema, // typed object, not an open array\n trustedClientIp: z.string(), // derived behind Firebase/Cloudflare; restricted, INDEX-EXEMPT field\n userAgent: z.string().max(256), // truncated to 256 chars, normalized\n at: z.number(),\n sessionId: z.string(),\n retentionClass: EventProvenanceRetentionClassSchema,\n}).strict();\nexport type EventProvenanceV1 = z.infer<typeof EventProvenanceV1Schema>;\n\n// ===========================================================================\n// §A6 — routine-retention build defaults (counsel may only SHORTEN). These are the\n// hold-aware deletion worker's TTL inputs; days, not ms. `reportSubmit` has NO\n// routine TTL — it is retained with the case.\n// ===========================================================================\n\n/** Routine TTL (days) by kind — build default; counsel may only shorten. */\nexport const EVENT_PROVENANCE_ROUTINE_TTL_DAYS = {\n uploadInit: 90,\n uploadFinalize: 90,\n messageSend: 90,\n login: 30,\n // reportSubmit: retained with the case — no routine TTL.\n} as const;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/doc-schemas/safety/report.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/doc-schemas/safety/report.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmBxB;;;;;;;;;;;wDAWwD;AACxD,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAMjD;sFACsF;AACtF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAe9B,CAAC;AACZ,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAMlF;wBACwB;AACxB,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAc9B,CAAC;AACZ,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAMlF;;;;4EAI4E;AAC5E,eAAO,MAAM,uBAAuB;;;;;;kBAMzB,CAAC;AACZ,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAMxE,mEAAmE;AACnE,eAAO,MAAM,+BAA+B;;;;;EAK1C,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF;;;wBAGwB;AACxB,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAa7B,CAAC;AACZ,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAMhF,4DAA4D;AAC5D,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAOhC,CAAC;AACZ,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAMtF;;;;yFAIyF;AACzF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAerB,CAAC;AACZ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// Trust & Safety — the report spine (Appendix A §A1, Finding-H1).
|
|
2
2
|
//
|
|
3
3
|
// The canonical report-target contract produced by the server `resolveReportTarget()`
|
|
4
|
-
// resolver
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// resolver plus the protected report root + public projection. Every shape here is
|
|
5
|
+
// transcribed verbatim from the frozen Trust & Safety spec (Appendix A §A1) — no
|
|
6
|
+
// invented values, no placeholders; the durable design owner is ttt-prod
|
|
7
|
+
// docs/design/content-moderation-and-reporting.md.
|
|
7
8
|
//
|
|
8
9
|
// SHARED enums + the target locator come from ./foundation.js (the single source for
|
|
9
10
|
// every cross-cluster enum); they are NEVER redefined here.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/report.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — the report spine (Appendix A §A1, Finding-H1).\n//\n// The canonical report-target contract produced by the server `resolveReportTarget()`\n// resolver (Phase 1 step 2) plus the protected report root + public projection. Every\n// shape here is transcribed verbatim from docs/code_changes_needed/trust-and-safety/\n// IMPLEMENTATION_PLAN.md Appendix A §A1 — no invented values, no placeholders.\n//\n// SHARED enums + the target locator come from ./foundation.js (the single source for\n// every cross-cluster enum); they are NEVER redefined here.\n//\n// Collection bindings (../registry.ts): `contentReports/{reportId}` →\n// `ProtectedReportRootV1Schema`, `contentReports/{reportId}/publicProjection/{reportId}`\n// → `ReportPublicProjectionV1Schema`, and `activeReportGroups/{groupKey}` →\n// `ReportGroupV1Schema`. These REPLACED the legacy loose-string report/group schemas; the\n// report DOC shape now lives entirely in this file.\n\nimport { z } from 'zod';\nimport {\n ReportReasonSchema,\n ReportableItemTypeSchema,\n ProtectedForkSchema,\n TargetLocatorV1Schema,\n} from './foundation.js';\nimport {\n MAX_REPORT_NARRATIVE_LENGTH,\n MAX_REPORT_SNAPSHOT_TEXT_LENGTH,\n} from '../../constants/business.js';\n\n// ===========================================================================\n// Canonical-key version token. The key formulas are DEFINED below as comments\n// (deterministic IDs are documented, never computed in this schema layer); the\n// server resolver/writer computes them. Bump this token if any formula input\n// set or hashing scheme changes.\n// ===========================================================================\n\n/** Version token folded into every canonical key formula below.\n *\n * v2 (pre-launch, no migration): two coordinated formula-input changes ride this\n * single bump —\n * (1) `canonicalTargetKey` composition is now INJECTIVE: each field is\n * length-prefixed (`len:value`) before joining, so no pair of adjacent\n * attacker-controlled fields (chat `canonicalParentPath` + `canonicalItemId`)\n * can produce a colliding preimage across different (channel, message) pairs.\n * (2) `revision` is derived from CONTENT-relevant state only (the content-edit\n * stamp `updatedAt`, falling back to `createdAt`) — NEVER the Firestore write\n * clock (`updateTime`). Counter writes (likes/votes/follows) no longer fragment\n * report groups or defeat per-reporter dedupe. */\nexport const REPORT_CANONICAL_KEY_VERSION = 'v2';\n\n// ===========================================================================\n// A1 — Server resolver result (ResolvedReportTargetV1)\n// ===========================================================================\n\n/** The server resolver result. The client `reportedItemId`/`reportedUserId` are\n * hints only; every field here is re-derived server-side at the reported revision. */\nexport const ResolvedReportTargetV1Schema = z.object({\n schemaVersion: z.literal(1),\n itemType: ReportableItemTypeSchema,\n canonicalParentPath: z.string(), // server-derived parent doc path\n canonicalItemId: z.string(), // server-derived item id (NEVER the client hint)\n revision: z.number(), // reported content revision — derived from the content-edit stamp\n // (updatedAt, falling back to createdAt), NEVER the write clock (updateTime)\n ownerUid: z.string(), // server-derived owner/sender uid (NOT client-supplied)\n ownerBlockKey: z.string(), // derived owner block key\n mediaAssetId: z.string().optional(), // typed per surface\n channelId: z.string().optional(),\n messageId: z.string().optional(),\n attachmentId: z.string().optional(),\n locator: TargetLocatorV1Schema, // the §A11 discriminated locator for downstream hold/removal\n resolvedAt: z.number(),\n}).strict();\nexport type ResolvedReportTargetV1 = z.infer<typeof ResolvedReportTargetV1Schema>;\n\n// ===========================================================================\n// A1 — Sanitized frozen snapshot (ReportTargetSnapshotV1)\n// ===========================================================================\n\n/** The sanitized frozen snapshot captured at resolve time — no reporter identity,\n * no PII; immutable. */\nexport const ReportTargetSnapshotV1Schema = z.object({\n schemaVersion: z.literal(1),\n itemType: ReportableItemTypeSchema,\n canonicalItemId: z.string(),\n revision: z.number(),\n contentSummaryRef: z.string(), // pointer to a sanitized content snapshot (restricted)\n contentHashes: z.array(z.string()).max(16).optional(),\n // [H-11/EUAS-013/R14] The sanitized REPORTED CONTENT captured at report time, so an author can't edit\n // the violating text/media out before review and have the operator see only the cleaned live doc\n // (edit-to-evade). `capturedText` = the bounded reported text/title/description (NO PII);\n // `capturedMediaAssetIds` = the reported media asset ids. Frozen + immutable like the rest.\n capturedText: z.string().max(MAX_REPORT_SNAPSHOT_TEXT_LENGTH).optional(),\n capturedMediaAssetIds: z.array(z.string()).max(32).optional(),\n capturedAt: z.number(),\n}).strict();\nexport type ReportTargetSnapshotV1 = z.infer<typeof ReportTargetSnapshotV1Schema>;\n\n// ===========================================================================\n// A1 — Segregated reporter narrative (NarrativeRecordV1)\n// ===========================================================================\n\n/** The reporter's free-text narrative — segregated reporter PII. Lives in a\n * restricted subcollection (`contentReports/{reportId}/private/narrative`),\n * admin-read-only, client-write-forbidden; NEVER inlined on the report root or\n * the public projection. The frozen target snapshot is stored alongside it at\n * `contentReports/{reportId}/private/snapshot` (ReportTargetSnapshotV1). */\nexport const NarrativeRecordV1Schema = z.object({\n schemaVersion: z.literal(1),\n reportId: z.string().min(1),\n reporterUid: z.string().min(1), // stored so account-erasure can scrub the narrative\n text: z.string().min(1).max(MAX_REPORT_NARRATIVE_LENGTH),\n createdAt: z.number(),\n}).strict();\nexport type NarrativeRecordV1 = z.infer<typeof NarrativeRecordV1Schema>;\n\n// ===========================================================================\n// A1 — Protected report root (ProtectedReportRootV1)\n// ===========================================================================\n\n/** Cluster-local lifecycle status of the protected report root. */\nexport const ProtectedReportRootStatusSchema = z.enum([\n 'pending_review',\n 'grouped',\n 'actioned',\n 'dismissed',\n]);\nexport type ProtectedReportRootStatus = z.infer<typeof ProtectedReportRootStatusSchema>;\n\n/** The protected report root (restricted — reporter identity + narrative segregated).\n * FUTURE shape of the EXISTING `contentReports/{reportId}` collection (rebinding\n * deferred to the app leg). `protectedFork` is set ONLY by the protected branch\n * (Phase 1 step 2a). */\nexport const ProtectedReportRootV1Schema = z.object({\n schemaVersion: z.literal(1),\n reportId: z.string().min(1), // = sha256(lp(version) + lp(reporterUid) + lp(canonicalTargetKey)) — see injective formulas below\n reporterUid: z.string().min(1),\n reason: ReportReasonSchema,\n resolvedTarget: ResolvedReportTargetV1Schema,\n snapshotRef: z.string(), // → ReportTargetSnapshotV1\n canonicalTargetKey: z.string(), // see formula below\n narrativeRef: z.string().optional(),\n protectedFork: ProtectedForkSchema.optional(), // set ONLY by the protected branch (Phase 1 step 2a)\n status: ProtectedReportRootStatusSchema,\n createdAt: z.number(),\n updatedAt: z.number(),\n}).strict();\nexport type ProtectedReportRootV1 = z.infer<typeof ProtectedReportRootV1Schema>;\n\n// ===========================================================================\n// A1 — Public projection (ReportPublicProjectionV1)\n// ===========================================================================\n\n/** Public projection — no reporter identity / narrative. */\nexport const ReportPublicProjectionV1Schema = z.object({\n schemaVersion: z.literal(1),\n reportId: z.string().min(1),\n itemType: ReportableItemTypeSchema,\n reason: ReportReasonSchema,\n status: ProtectedReportRootStatusSchema,\n createdAt: z.number(),\n}).strict();\nexport type ReportPublicProjectionV1 = z.infer<typeof ReportPublicProjectionV1Schema>;\n\n// ===========================================================================\n// A1 — Report group (ReportGroupV1) — dedup/count group keyed by canonicalTargetKey\n// ===========================================================================\n\n/** The dedup/count group for all reports of the same target+revision. The group key\n * IS the `canonicalTargetKey` (== reportGroupKey). NO trusted client owner field — the\n * owner lives on the restricted ProtectedReportRootV1 (resolvedTarget.ownerUid), never\n * here. An app-side trigger maintains the counts; this is the public-ish group surface\n * the admin browse + admin-task queue read. Bound to `activeReportGroups/{groupKey}`. */\nexport const ReportGroupV1Schema = z.object({\n schemaVersion: z.literal(1),\n groupKey: z.string().min(1), // = canonicalTargetKey\n itemType: ReportableItemTypeSchema,\n totalReports: z.number(),\n highestReasonScore: z.number(),\n lastReportAt: z.number(),\n latestReason: ReportReasonSchema,\n // [R12] close-lifecycle states. An ordinary report's admin close (hide/remove/restore) moves the\n // group to `processing` and STAYS in the queue — it is NEVER cleared on the click. The group flips\n // to the terminal `resolved` ONLY when the edge serving-deny (hide/remove) or block-clear (restore)\n // VERIFIES. If the content-serving-sync saga exhausts its retries (dead-letter), the group moves to\n // `failed` — kept in the queue, surfaced in the Safety Console failed-jobs view, with a Restart that\n // re-arms the job. Both are explicit values (never derived).\n status: z.enum(['pending', 'reviewing', 'processing', 'failed', 'resolved']),\n}).strict();\nexport type ReportGroupV1 = z.infer<typeof ReportGroupV1Schema>;\n\n// ===========================================================================\n// Canonical keys (DEFINED — not inline prose). Computed server-side by the\n// resolver/writer; documented here, NOT computed in this schema layer. The\n// `version` token in each formula is `REPORT_CANONICAL_KEY_VERSION` above (now v2).\n//\n// canonicalTargetKey = sha256( lp(version) + lp(itemType) + lp(canonicalParentPath)\n// + lp(canonicalItemId) + lp(String(revision)) )\n// // v2: INJECTIVE composition. lp(s) length-prefixes each field\n// // as `<byteLength>:<s>` (or hash each field separately) so no ':'\n// // ambiguity can straddle two adjacent attacker-controlled fields.\n// // The old `[...].join(':')` was collision-prone for chat targets,\n// // whose canonicalParentPath + canonicalItemId are BOTH client-\n// // derived strings (synthetic:chat:<channelRef> / <messageId>).\n// // `revision` is the CONTENT revision (content-edit stamp, never\n// // the Firestore write clock) — see REPORT_CANONICAL_KEY_VERSION.\n//\n// reportId = sha256( lp(version) + lp(reporterUid) + lp(canonicalTargetKey) )\n// // deterministic dup-key: one report per reporter+target+revision.\n// // This determinism is what makes the protected branch's retry a\n// // no-op on the already-committed hold (Phase 1 step 2a).\n//\n// reportGroupKey = canonicalTargetKey\n// // grouping key: all reporters of the same target+revision.\n// ===========================================================================\n"]}
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/doc-schemas/safety/report.ts"],"names":[],"mappings":"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","sourcesContent":["// Trust & Safety — the report spine (Appendix A §A1, Finding-H1).\n//\n// The canonical report-target contract produced by the server `resolveReportTarget()`\n// resolver plus the protected report root + public projection. Every shape here is\n// transcribed verbatim from the frozen Trust & Safety spec (Appendix A §A1) — no\n// invented values, no placeholders; the durable design owner is ttt-prod\n// docs/design/content-moderation-and-reporting.md.\n//\n// SHARED enums + the target locator come from ./foundation.js (the single source for\n// every cross-cluster enum); they are NEVER redefined here.\n//\n// Collection bindings (../registry.ts): `contentReports/{reportId}` →\n// `ProtectedReportRootV1Schema`, `contentReports/{reportId}/publicProjection/{reportId}`\n// → `ReportPublicProjectionV1Schema`, and `activeReportGroups/{groupKey}` →\n// `ReportGroupV1Schema`. These REPLACED the legacy loose-string report/group schemas; the\n// report DOC shape now lives entirely in this file.\n\nimport { z } from 'zod';\nimport {\n ReportReasonSchema,\n ReportableItemTypeSchema,\n ProtectedForkSchema,\n TargetLocatorV1Schema,\n} from './foundation.js';\nimport {\n MAX_REPORT_NARRATIVE_LENGTH,\n MAX_REPORT_SNAPSHOT_TEXT_LENGTH,\n} from '../../constants/business.js';\n\n// ===========================================================================\n// Canonical-key version token. The key formulas are DEFINED below as comments\n// (deterministic IDs are documented, never computed in this schema layer); the\n// server resolver/writer computes them. Bump this token if any formula input\n// set or hashing scheme changes.\n// ===========================================================================\n\n/** Version token folded into every canonical key formula below.\n *\n * v2 (pre-launch, no migration): two coordinated formula-input changes ride this\n * single bump —\n * (1) `canonicalTargetKey` composition is now INJECTIVE: each field is\n * length-prefixed (`len:value`) before joining, so no pair of adjacent\n * attacker-controlled fields (chat `canonicalParentPath` + `canonicalItemId`)\n * can produce a colliding preimage across different (channel, message) pairs.\n * (2) `revision` is derived from CONTENT-relevant state only (the content-edit\n * stamp `updatedAt`, falling back to `createdAt`) — NEVER the Firestore write\n * clock (`updateTime`). Counter writes (likes/votes/follows) no longer fragment\n * report groups or defeat per-reporter dedupe. */\nexport const REPORT_CANONICAL_KEY_VERSION = 'v2';\n\n// ===========================================================================\n// A1 — Server resolver result (ResolvedReportTargetV1)\n// ===========================================================================\n\n/** The server resolver result. The client `reportedItemId`/`reportedUserId` are\n * hints only; every field here is re-derived server-side at the reported revision. */\nexport const ResolvedReportTargetV1Schema = z.object({\n schemaVersion: z.literal(1),\n itemType: ReportableItemTypeSchema,\n canonicalParentPath: z.string(), // server-derived parent doc path\n canonicalItemId: z.string(), // server-derived item id (NEVER the client hint)\n revision: z.number(), // reported content revision — derived from the content-edit stamp\n // (updatedAt, falling back to createdAt), NEVER the write clock (updateTime)\n ownerUid: z.string(), // server-derived owner/sender uid (NOT client-supplied)\n ownerBlockKey: z.string(), // derived owner block key\n mediaAssetId: z.string().optional(), // typed per surface\n channelId: z.string().optional(),\n messageId: z.string().optional(),\n attachmentId: z.string().optional(),\n locator: TargetLocatorV1Schema, // the §A11 discriminated locator for downstream hold/removal\n resolvedAt: z.number(),\n}).strict();\nexport type ResolvedReportTargetV1 = z.infer<typeof ResolvedReportTargetV1Schema>;\n\n// ===========================================================================\n// A1 — Sanitized frozen snapshot (ReportTargetSnapshotV1)\n// ===========================================================================\n\n/** The sanitized frozen snapshot captured at resolve time — no reporter identity,\n * no PII; immutable. */\nexport const ReportTargetSnapshotV1Schema = z.object({\n schemaVersion: z.literal(1),\n itemType: ReportableItemTypeSchema,\n canonicalItemId: z.string(),\n revision: z.number(),\n contentSummaryRef: z.string(), // pointer to a sanitized content snapshot (restricted)\n contentHashes: z.array(z.string()).max(16).optional(),\n // [H-11/EUAS-013/R14] The sanitized REPORTED CONTENT captured at report time, so an author can't edit\n // the violating text/media out before review and have the operator see only the cleaned live doc\n // (edit-to-evade). `capturedText` = the bounded reported text/title/description (NO PII);\n // `capturedMediaAssetIds` = the reported media asset ids. Frozen + immutable like the rest.\n capturedText: z.string().max(MAX_REPORT_SNAPSHOT_TEXT_LENGTH).optional(),\n capturedMediaAssetIds: z.array(z.string()).max(32).optional(),\n capturedAt: z.number(),\n}).strict();\nexport type ReportTargetSnapshotV1 = z.infer<typeof ReportTargetSnapshotV1Schema>;\n\n// ===========================================================================\n// A1 — Segregated reporter narrative (NarrativeRecordV1)\n// ===========================================================================\n\n/** The reporter's free-text narrative — segregated reporter PII. Lives in a\n * restricted subcollection (`contentReports/{reportId}/private/narrative`),\n * admin-read-only, client-write-forbidden; NEVER inlined on the report root or\n * the public projection. The frozen target snapshot is stored alongside it at\n * `contentReports/{reportId}/private/snapshot` (ReportTargetSnapshotV1). */\nexport const NarrativeRecordV1Schema = z.object({\n schemaVersion: z.literal(1),\n reportId: z.string().min(1),\n reporterUid: z.string().min(1), // stored so account-erasure can scrub the narrative\n text: z.string().min(1).max(MAX_REPORT_NARRATIVE_LENGTH),\n createdAt: z.number(),\n}).strict();\nexport type NarrativeRecordV1 = z.infer<typeof NarrativeRecordV1Schema>;\n\n// ===========================================================================\n// A1 — Protected report root (ProtectedReportRootV1)\n// ===========================================================================\n\n/** Cluster-local lifecycle status of the protected report root. */\nexport const ProtectedReportRootStatusSchema = z.enum([\n 'pending_review',\n 'grouped',\n 'actioned',\n 'dismissed',\n]);\nexport type ProtectedReportRootStatus = z.infer<typeof ProtectedReportRootStatusSchema>;\n\n/** The protected report root (restricted — reporter identity + narrative segregated).\n * FUTURE shape of the EXISTING `contentReports/{reportId}` collection (rebinding\n * deferred to the app leg). `protectedFork` is set ONLY by the protected branch\n * (Phase 1 step 2a). */\nexport const ProtectedReportRootV1Schema = z.object({\n schemaVersion: z.literal(1),\n reportId: z.string().min(1), // = sha256(lp(version) + lp(reporterUid) + lp(canonicalTargetKey)) — see injective formulas below\n reporterUid: z.string().min(1),\n reason: ReportReasonSchema,\n resolvedTarget: ResolvedReportTargetV1Schema,\n snapshotRef: z.string(), // → ReportTargetSnapshotV1\n canonicalTargetKey: z.string(), // see formula below\n narrativeRef: z.string().optional(),\n protectedFork: ProtectedForkSchema.optional(), // set ONLY by the protected branch (Phase 1 step 2a)\n status: ProtectedReportRootStatusSchema,\n createdAt: z.number(),\n updatedAt: z.number(),\n}).strict();\nexport type ProtectedReportRootV1 = z.infer<typeof ProtectedReportRootV1Schema>;\n\n// ===========================================================================\n// A1 — Public projection (ReportPublicProjectionV1)\n// ===========================================================================\n\n/** Public projection — no reporter identity / narrative. */\nexport const ReportPublicProjectionV1Schema = z.object({\n schemaVersion: z.literal(1),\n reportId: z.string().min(1),\n itemType: ReportableItemTypeSchema,\n reason: ReportReasonSchema,\n status: ProtectedReportRootStatusSchema,\n createdAt: z.number(),\n}).strict();\nexport type ReportPublicProjectionV1 = z.infer<typeof ReportPublicProjectionV1Schema>;\n\n// ===========================================================================\n// A1 — Report group (ReportGroupV1) — dedup/count group keyed by canonicalTargetKey\n// ===========================================================================\n\n/** The dedup/count group for all reports of the same target+revision. The group key\n * IS the `canonicalTargetKey` (== reportGroupKey). NO trusted client owner field — the\n * owner lives on the restricted ProtectedReportRootV1 (resolvedTarget.ownerUid), never\n * here. An app-side trigger maintains the counts; this is the public-ish group surface\n * the admin browse + admin-task queue read. Bound to `activeReportGroups/{groupKey}`. */\nexport const ReportGroupV1Schema = z.object({\n schemaVersion: z.literal(1),\n groupKey: z.string().min(1), // = canonicalTargetKey\n itemType: ReportableItemTypeSchema,\n totalReports: z.number(),\n highestReasonScore: z.number(),\n lastReportAt: z.number(),\n latestReason: ReportReasonSchema,\n // [R12] close-lifecycle states. An ordinary report's admin close (hide/remove/restore) moves the\n // group to `processing` and STAYS in the queue — it is NEVER cleared on the click. The group flips\n // to the terminal `resolved` ONLY when the edge serving-deny (hide/remove) or block-clear (restore)\n // VERIFIES. If the content-serving-sync saga exhausts its retries (dead-letter), the group moves to\n // `failed` — kept in the queue, surfaced in the Safety Console failed-jobs view, with a Restart that\n // re-arms the job. Both are explicit values (never derived).\n status: z.enum(['pending', 'reviewing', 'processing', 'failed', 'resolved']),\n}).strict();\nexport type ReportGroupV1 = z.infer<typeof ReportGroupV1Schema>;\n\n// ===========================================================================\n// Canonical keys (DEFINED — not inline prose). Computed server-side by the\n// resolver/writer; documented here, NOT computed in this schema layer. The\n// `version` token in each formula is `REPORT_CANONICAL_KEY_VERSION` above (now v2).\n//\n// canonicalTargetKey = sha256( lp(version) + lp(itemType) + lp(canonicalParentPath)\n// + lp(canonicalItemId) + lp(String(revision)) )\n// // v2: INJECTIVE composition. lp(s) length-prefixes each field\n// // as `<byteLength>:<s>` (or hash each field separately) so no ':'\n// // ambiguity can straddle two adjacent attacker-controlled fields.\n// // The old `[...].join(':')` was collision-prone for chat targets,\n// // whose canonicalParentPath + canonicalItemId are BOTH client-\n// // derived strings (synthetic:chat:<channelRef> / <messageId>).\n// // `revision` is the CONTENT revision (content-edit stamp, never\n// // the Firestore write clock) — see REPORT_CANONICAL_KEY_VERSION.\n//\n// reportId = sha256( lp(version) + lp(reporterUid) + lp(canonicalTargetKey) )\n// // deterministic dup-key: one report per reporter+target+revision.\n// // This determinism is what makes the protected branch's retry a\n// // no-op on the already-committed hold (Phase 1 step 2a).\n//\n// reportGroupKey = canonicalTargetKey\n// // grouping key: all reporters of the same target+revision.\n// ===========================================================================\n"]}
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
// no doc ever lies about quarantine completion. Each saga is idempotent by
|
|
8
8
|
// `commandId`; the reconciler verifies external state, never a prior response.
|
|
9
9
|
//
|
|
10
|
-
// Every shape here is transcribed verbatim from
|
|
11
|
-
//
|
|
12
|
-
//
|
|
10
|
+
// Every shape here is transcribed verbatim from the frozen Trust & Safety spec
|
|
11
|
+
// (Appendix A §A5) — no invented values, no placeholders; the durable design owner
|
|
12
|
+
// is ttt-prod docs/design/csam-detection-and-response.md.
|
|
13
13
|
//
|
|
14
14
|
// SHARED enums come from ./foundation.js (the single source for every
|
|
15
15
|
// cross-cluster enum); they are NEVER redefined here. This cluster IMPORTS
|