@ttt-productions/ttt-core 0.79.13 → 0.79.14

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.
@@ -92,6 +92,7 @@ export declare const AccountDeletionRequestV1Schema: z.ZodObject<{
92
92
  scheduledScrubAt: z.ZodNumber;
93
93
  graceDays: z.ZodNumber;
94
94
  cancelledAt: z.ZodOptional<z.ZodNumber>;
95
+ tokenRevocationNextAttemptAt: z.ZodOptional<z.ZodNumber>;
95
96
  tokensRevokedAt: z.ZodOptional<z.ZodNumber>;
96
97
  scrubStartedAt: z.ZodOptional<z.ZodNumber>;
97
98
  parkedReason: z.ZodOptional<z.ZodString>;
@@ -1 +1 @@
1
- {"version":3,"file":"account-deletion.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/account-deletion.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gDAAgD;AAChD,eAAO,MAAM,kCAAkC;;;;;;;;EAU7C,CAAC;AACH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAE9F;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,iCAAiC;;;;;;;;CAQ2B,CAAC;AAEnE,0FAA0F;AAC1F,MAAM,MAAM,2BAA2B,GAAG;KACvC,CAAC,IAAI,4BAA4B,GAAG,CAAC,OAAO,iCAAiC,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK;CAC5G,CAAC,4BAA4B,CAAC,CAAC;AAEhC;;gFAEgF;AAChF,eAAO,MAAM,gCAAgC,EAAE,SAAS,2BAA2B,EAEmB,CAAC;AAEvG;;4FAE4F;AAC5F,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,2BAA2B,CAE9F;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;kBAmBtB,CAAC;AACZ,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,yEAAyE;AACzE,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAiChC,CAAC;AACZ,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC"}
1
+ {"version":3,"file":"account-deletion.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/account-deletion.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,gDAAgD;AAChD,eAAO,MAAM,kCAAkC;;;;;;;;EAU7C,CAAC;AACH,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAE9F;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,iCAAiC;;;;;;;;CAQ2B,CAAC;AAEnE,0FAA0F;AAC1F,MAAM,MAAM,2BAA2B,GAAG;KACvC,CAAC,IAAI,4BAA4B,GAAG,CAAC,OAAO,iCAAiC,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK;CAC5G,CAAC,4BAA4B,CAAC,CAAC;AAEhC;;gFAEgF;AAChF,eAAO,MAAM,gCAAgC,EAAE,SAAS,2BAA2B,EAEmB,CAAC;AAEvG;;4FAE4F;AAC5F,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,2BAA2B,CAE9F;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;kBAmBtB,CAAC;AACZ,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,yEAAyE;AACzE,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA+ChC,CAAC;AACZ,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC"}
@@ -118,12 +118,26 @@ export const AccountDeletionRequestV1Schema = z
118
118
  scheduledScrubAt: z.number(),
119
119
  graceDays: z.number(), // recorded for the audit/compliance trail (30 at launch)
120
120
  cancelledAt: z.number().optional(),
121
+ // Token-revocation obligation — the request doc IS the durable ledger (BACKEND-302 /
122
+ // QUALITY-104); no separate queue, worker collection, or dead-letter state exists.
123
+ //
124
+ // `tokenRevocationNextAttemptAt` is the DRAIN KEY: present ⇔ the revocation is still
125
+ // OWED. Set to `now` when the request is created; the scheduled worker's revocation
126
+ // drain queries `tokenRevocationNextAttemptAt <= now` (single-field range — deliberately
127
+ // no status clause and no composite index; every terminal transition clears the field,
128
+ // and the drain clears it on any non-active doc it meets, so "owed" means exactly
129
+ // "field present"). A failed attempt moves it forward (bounded backoff); a successful
130
+ // revoke DELETES it and stamps `tokensRevokedAt` in the same fenced update.
131
+ //
132
+ // The stamp is GENERATION-FENCED on `requestedAt`: the revoker snapshots `requestedAt`
133
+ // before calling Auth and stamps transactionally only if the doc still carries that
134
+ // value with an active status — a delayed revoke from a cancelled request must never
135
+ // mark a newly reopened request satisfied. Revocation is idempotent, so a skipped or
136
+ // lost stamp merely causes one redundant re-revoke.
137
+ tokenRevocationNextAttemptAt: z.number().optional(),
121
138
  // When the user's refresh tokens were revoked for THIS request ("account deletion signs
122
- // the user out of every session everywhere"). ABSENT = the obligation is still pending:
123
- // the request doc IS the durable state (BACKEND-302/QUALITY-104) the callable's
124
- // immediate revoke is only the accelerator, and the scheduled scrub-worker drain
125
- // re-revokes + stamps any ACTIVE request missing this field until it succeeds.
126
- // Revocation is idempotent, so a lost stamp merely causes one redundant re-revoke.
139
+ // the user out of every session everywhere"). The callable's immediate revoke is only
140
+ // the accelerator (BACKEND-301); the worker drain above is the guarantee.
127
141
  tokensRevokedAt: z.number().optional(),
128
142
  scrubStartedAt: z.number().optional(),
129
143
  // Why a scrub is parked (e.g. 'blocking safety hold over user data') — kept for
@@ -1 +1 @@
1
- {"version":3,"file":"account-deletion.js","sourceRoot":"","sources":["../../src/doc-schemas/account-deletion.ts"],"names":[],"mappings":"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","sourcesContent":["// Account-deletion / GDPR-erasure request SCHEMA — `accountDeletionRequests/{uid}`.\n//\n// N3 data-deletion flow. A user clicks \"delete account\" on their profile → a\n// request doc is created (one per user, doc id = uid, create-if-absent) and the\n// account is immediately deactivated/locked out. The request runs a 30-day grace\n// window (logging back in CANCELS it). After the window, the scheduled scrub\n// worker checks for any BLOCKING safety hold over the user's data:\n// - no hold → anonymize-in-place (scrub PII, release reserved name, anonymize\n// chat history, tombstone memberships) → `completed`.\n// - hold → `parkedOnHold` (re-checked periodically): resumes + `completed`\n// once cleared, or → `superseded` if it becomes a ban-for-cause /\n// evidence-preservation outcome (the erasure is overridden and the\n// data retained as evidence).\n//\n// The scrub itself deletes/anonymizes data across many collections; this doc is\n// ONLY the request lifecycle + the worker's resumable cursor.\n//\n// [C-02] Erasure-vs-safety-hold race fence. The destructive scrub and a safety\n// hold landing mid-scrub race over the SAME account. The fence is an epoch LEASE\n// stamped on THIS doc (`erasureLease`): the scrub transactionally acquires the\n// lease ONLY when the account owns no active blocking hold; every destructive\n// write re-checks the SAME epoch in its own transaction; and `commitSafetyHold`\n// (the SINGLE shared hold authority) reads this doc's live lease and PARKS the\n// erasure (revoking the epoch) before committing a hold against a leased account.\n// A revoked epoch makes every still-running destructive step a no-op. The lease\n// lives HERE — not a parallel safety-only deletion subsystem — so the one shared\n// hold/destructive contract owns the fence (engineering-rules ARCH-001).\n\nimport { z } from 'zod';\n\n/** Lifecycle of an account-deletion request. */\nexport const AccountDeletionRequestStatusSchema = z.enum([\n 'pending', // grace window running; user can still cancel by logging in\n 'cancelled', // user cancelled (logged back in) before the window elapsed\n 'scrubbing', // the scrub worker has started the anonymize-in-place erasure\n // [C-02] the scrub holds an ACTIVE erasure lease and is mid-destruction. A hold\n // landing now revokes the lease (→ parkedOnHold) so the scrub aborts deterministically.\n 'leased',\n 'parkedOnHold', // erasure deferred — a blocking safety hold covers the user's data\n 'completed', // erasure finished\n 'superseded', // overridden by a ban-for-cause / evidence-preservation outcome\n]);\nexport type AccountDeletionRequestStatus = z.infer<typeof AccountDeletionRequestStatusSchema>;\n\n/**\n * ACTIVE = the request is still OPEN and still cancellable. This is the one predicate the\n * lifecycle's enforcement points share — `requestAccountDeletion`'s idempotent re-return of the\n * existing schedule, `cancelAccountDeletion`'s cancel gate, the scrub worker's due-request query,\n * and the client's live own-request read — each of which previously restated\n * `status === 'pending' || status === 'parkedOnHold'` locally (ARCH-102).\n *\n * Declared as an EXHAUSTIVE Record over the status union, not as a subset array: a subset array\n * only catches a REMOVED member, whereas adding a lifecycle status must be a compile error here\n * until that status is classified. A new status silently defaulting to \"not active\" is exactly the\n * drift this classification exists to prevent.\n *\n * `scrubbing` / `leased` are deliberately NOT active — the destructive erasure has already begun,\n * so there is no schedule left to re-offer and nothing left to cancel. `cancelled` / `completed` /\n * `superseded` are terminal.\n */\nconst DELETION_REQUEST_STATUS_IS_ACTIVE = {\n pending: true,\n cancelled: false,\n scrubbing: false,\n leased: false,\n parkedOnHold: true,\n completed: false,\n superseded: false,\n} as const satisfies Record<AccountDeletionRequestStatus, boolean>;\n\n/** The statuses classified ACTIVE above, as a literal union — derived, never restated. */\nexport type ActiveDeletionRequestStatus = {\n [K in AccountDeletionRequestStatus]: (typeof DELETION_REQUEST_STATUS_IS_ACTIVE)[K] extends true ? K : never;\n}[AccountDeletionRequestStatus];\n\n/** The ACTIVE (open, still-cancellable) deletion-request statuses, projected from the\n * classification above in union-declaration order — so it can also feed a Firestore\n * `where('status', 'in', ACTIVE_DELETION_REQUEST_STATUSES)` query directly. */\nexport const ACTIVE_DELETION_REQUEST_STATUSES: readonly ActiveDeletionRequestStatus[] = (\n Object.keys(DELETION_REQUEST_STATUS_IS_ACTIVE) as AccountDeletionRequestStatus[]\n).filter((status): status is ActiveDeletionRequestStatus => DELETION_REQUEST_STATUS_IS_ACTIVE[status]);\n\n/** True for an ACTIVE (open, still-cancellable) deletion request. Takes `unknown` because every\n * caller reads the status off an unvalidated Firestore doc: anything outside the canonical active\n * set — a terminal/mid-scrub status, an unrecognized value, a missing field — is false. */\nexport function isActiveDeletionRequest(status: unknown): status is ActiveDeletionRequestStatus {\n return typeof status === 'string' && (ACTIVE_DELETION_REQUEST_STATUSES as readonly string[]).includes(status);\n}\n\n/**\n * [C-02] The erasure LEASE / epoch token — the race fence between the destructive\n * scrub and a mid-scrub safety hold.\n *\n * The scrub acquires this transactionally ONLY when the account owns no active\n * blocking hold; it then re-verifies the SAME `epoch` inside every destructive\n * Firestore transaction and immediately before AND after each non-transactional\n * external delete (Auth/Storage). `commitSafetyHold` reads this lease and, when it\n * is `active`, REVOKES it (sets `revokedByHold`/`revokedAt`, status → `parkedOnHold`)\n * in the SAME transaction that commits the hold — so a hold deterministically wins\n * the race and the scrub, finding its epoch revoked on the next check, aborts into\n * a recoverable parked state without finishing the destruction.\n */\nexport const ErasureLeaseV1Schema = z\n .object({\n /** Monotonic acquisition token. The \"live lease\" identity: every destructive step\n * re-reads the doc and proceeds ONLY if this still equals the epoch it acquired. */\n epoch: z.number().int().nonnegative(),\n /** 'active' = the scrub holds the lease; 'revoked' = a hold reclaimed it mid-scrub\n * (the scrub must abort); 'released' = the scrub finished/relinquished cleanly. */\n state: z.enum(['active', 'revoked', 'released']),\n acquiredAt: z.number(),\n /** Staleness boundary. A still-`active` lease past this is presumed crashed and may\n * be safely superseded by a fresh acquisition (idempotent retry / crash recovery). */\n expiresAt: z.number(),\n /** Last destructive phase the scrub reached under this epoch (observability + recovery). */\n phase: z.string().optional(),\n /** Set when a hold revoked the lease — the caseId/refId of the winning hold (audit trail). */\n revokedByHoldRefId: z.string().min(1).optional(),\n revokedAt: z.number().optional(),\n releasedAt: z.number().optional(),\n })\n .strict();\nexport type ErasureLeaseV1 = z.infer<typeof ErasureLeaseV1Schema>;\n\n/** `accountDeletionRequests/{uid}` — one per user; doc id IS the uid. */\nexport const AccountDeletionRequestV1Schema = z\n .object({\n schemaVersion: z.literal(1),\n uid: z.string().min(1),\n status: AccountDeletionRequestStatusSchema,\n requestedAt: z.number(),\n // requestedAt + graceDays; the scrub worker queries status='pending' AND\n // scheduledScrubAt <= now (composite index, ttt-prod firestore.indexes.json).\n scheduledScrubAt: z.number(),\n graceDays: z.number(), // recorded for the audit/compliance trail (30 at launch)\n cancelledAt: z.number().optional(),\n // When the user's refresh tokens were revoked for THIS request (\"account deletion signs\n // the user out of every session everywhere\"). ABSENT = the obligation is still pending:\n // the request doc IS the durable state (BACKEND-302/QUALITY-104) — the callable's\n // immediate revoke is only the accelerator, and the scheduled scrub-worker drain\n // re-revokes + stamps any ACTIVE request missing this field until it succeeds.\n // Revocation is idempotent, so a lost stamp merely causes one redundant re-revoke.\n tokensRevokedAt: z.number().optional(),\n scrubStartedAt: z.number().optional(),\n // Why a scrub is parked (e.g. 'blocking safety hold over user data') — kept for\n // the GDPR compliance record so a deferred erasure is explainable.\n parkedReason: z.string().optional(),\n parkedAt: z.number().optional(),\n lastHoldCheckAt: z.number().optional(),\n completedAt: z.number().optional(),\n supersededAt: z.number().optional(),\n supersededReason: z.string().optional(),\n // [C-02] the erasure-vs-hold race fence (see ErasureLeaseV1). Absent until the\n // scrub first acquires the lease; thereafter it carries the live epoch + state.\n erasureLease: ErasureLeaseV1Schema.optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n })\n .strict();\nexport type AccountDeletionRequestV1 = z.infer<typeof AccountDeletionRequestV1Schema>;\n"]}
1
+ {"version":3,"file":"account-deletion.js","sourceRoot":"","sources":["../../src/doc-schemas/account-deletion.ts"],"names":[],"mappings":"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","sourcesContent":["// Account-deletion / GDPR-erasure request SCHEMA — `accountDeletionRequests/{uid}`.\n//\n// N3 data-deletion flow. A user clicks \"delete account\" on their profile → a\n// request doc is created (one per user, doc id = uid, create-if-absent) and the\n// account is immediately deactivated/locked out. The request runs a 30-day grace\n// window (logging back in CANCELS it). After the window, the scheduled scrub\n// worker checks for any BLOCKING safety hold over the user's data:\n// - no hold → anonymize-in-place (scrub PII, release reserved name, anonymize\n// chat history, tombstone memberships) → `completed`.\n// - hold → `parkedOnHold` (re-checked periodically): resumes + `completed`\n// once cleared, or → `superseded` if it becomes a ban-for-cause /\n// evidence-preservation outcome (the erasure is overridden and the\n// data retained as evidence).\n//\n// The scrub itself deletes/anonymizes data across many collections; this doc is\n// ONLY the request lifecycle + the worker's resumable cursor.\n//\n// [C-02] Erasure-vs-safety-hold race fence. The destructive scrub and a safety\n// hold landing mid-scrub race over the SAME account. The fence is an epoch LEASE\n// stamped on THIS doc (`erasureLease`): the scrub transactionally acquires the\n// lease ONLY when the account owns no active blocking hold; every destructive\n// write re-checks the SAME epoch in its own transaction; and `commitSafetyHold`\n// (the SINGLE shared hold authority) reads this doc's live lease and PARKS the\n// erasure (revoking the epoch) before committing a hold against a leased account.\n// A revoked epoch makes every still-running destructive step a no-op. The lease\n// lives HERE — not a parallel safety-only deletion subsystem — so the one shared\n// hold/destructive contract owns the fence (engineering-rules ARCH-001).\n\nimport { z } from 'zod';\n\n/** Lifecycle of an account-deletion request. */\nexport const AccountDeletionRequestStatusSchema = z.enum([\n 'pending', // grace window running; user can still cancel by logging in\n 'cancelled', // user cancelled (logged back in) before the window elapsed\n 'scrubbing', // the scrub worker has started the anonymize-in-place erasure\n // [C-02] the scrub holds an ACTIVE erasure lease and is mid-destruction. A hold\n // landing now revokes the lease (→ parkedOnHold) so the scrub aborts deterministically.\n 'leased',\n 'parkedOnHold', // erasure deferred — a blocking safety hold covers the user's data\n 'completed', // erasure finished\n 'superseded', // overridden by a ban-for-cause / evidence-preservation outcome\n]);\nexport type AccountDeletionRequestStatus = z.infer<typeof AccountDeletionRequestStatusSchema>;\n\n/**\n * ACTIVE = the request is still OPEN and still cancellable. This is the one predicate the\n * lifecycle's enforcement points share — `requestAccountDeletion`'s idempotent re-return of the\n * existing schedule, `cancelAccountDeletion`'s cancel gate, the scrub worker's due-request query,\n * and the client's live own-request read — each of which previously restated\n * `status === 'pending' || status === 'parkedOnHold'` locally (ARCH-102).\n *\n * Declared as an EXHAUSTIVE Record over the status union, not as a subset array: a subset array\n * only catches a REMOVED member, whereas adding a lifecycle status must be a compile error here\n * until that status is classified. A new status silently defaulting to \"not active\" is exactly the\n * drift this classification exists to prevent.\n *\n * `scrubbing` / `leased` are deliberately NOT active — the destructive erasure has already begun,\n * so there is no schedule left to re-offer and nothing left to cancel. `cancelled` / `completed` /\n * `superseded` are terminal.\n */\nconst DELETION_REQUEST_STATUS_IS_ACTIVE = {\n pending: true,\n cancelled: false,\n scrubbing: false,\n leased: false,\n parkedOnHold: true,\n completed: false,\n superseded: false,\n} as const satisfies Record<AccountDeletionRequestStatus, boolean>;\n\n/** The statuses classified ACTIVE above, as a literal union — derived, never restated. */\nexport type ActiveDeletionRequestStatus = {\n [K in AccountDeletionRequestStatus]: (typeof DELETION_REQUEST_STATUS_IS_ACTIVE)[K] extends true ? K : never;\n}[AccountDeletionRequestStatus];\n\n/** The ACTIVE (open, still-cancellable) deletion-request statuses, projected from the\n * classification above in union-declaration order — so it can also feed a Firestore\n * `where('status', 'in', ACTIVE_DELETION_REQUEST_STATUSES)` query directly. */\nexport const ACTIVE_DELETION_REQUEST_STATUSES: readonly ActiveDeletionRequestStatus[] = (\n Object.keys(DELETION_REQUEST_STATUS_IS_ACTIVE) as AccountDeletionRequestStatus[]\n).filter((status): status is ActiveDeletionRequestStatus => DELETION_REQUEST_STATUS_IS_ACTIVE[status]);\n\n/** True for an ACTIVE (open, still-cancellable) deletion request. Takes `unknown` because every\n * caller reads the status off an unvalidated Firestore doc: anything outside the canonical active\n * set — a terminal/mid-scrub status, an unrecognized value, a missing field — is false. */\nexport function isActiveDeletionRequest(status: unknown): status is ActiveDeletionRequestStatus {\n return typeof status === 'string' && (ACTIVE_DELETION_REQUEST_STATUSES as readonly string[]).includes(status);\n}\n\n/**\n * [C-02] The erasure LEASE / epoch token — the race fence between the destructive\n * scrub and a mid-scrub safety hold.\n *\n * The scrub acquires this transactionally ONLY when the account owns no active\n * blocking hold; it then re-verifies the SAME `epoch` inside every destructive\n * Firestore transaction and immediately before AND after each non-transactional\n * external delete (Auth/Storage). `commitSafetyHold` reads this lease and, when it\n * is `active`, REVOKES it (sets `revokedByHold`/`revokedAt`, status → `parkedOnHold`)\n * in the SAME transaction that commits the hold — so a hold deterministically wins\n * the race and the scrub, finding its epoch revoked on the next check, aborts into\n * a recoverable parked state without finishing the destruction.\n */\nexport const ErasureLeaseV1Schema = z\n .object({\n /** Monotonic acquisition token. The \"live lease\" identity: every destructive step\n * re-reads the doc and proceeds ONLY if this still equals the epoch it acquired. */\n epoch: z.number().int().nonnegative(),\n /** 'active' = the scrub holds the lease; 'revoked' = a hold reclaimed it mid-scrub\n * (the scrub must abort); 'released' = the scrub finished/relinquished cleanly. */\n state: z.enum(['active', 'revoked', 'released']),\n acquiredAt: z.number(),\n /** Staleness boundary. A still-`active` lease past this is presumed crashed and may\n * be safely superseded by a fresh acquisition (idempotent retry / crash recovery). */\n expiresAt: z.number(),\n /** Last destructive phase the scrub reached under this epoch (observability + recovery). */\n phase: z.string().optional(),\n /** Set when a hold revoked the lease — the caseId/refId of the winning hold (audit trail). */\n revokedByHoldRefId: z.string().min(1).optional(),\n revokedAt: z.number().optional(),\n releasedAt: z.number().optional(),\n })\n .strict();\nexport type ErasureLeaseV1 = z.infer<typeof ErasureLeaseV1Schema>;\n\n/** `accountDeletionRequests/{uid}` — one per user; doc id IS the uid. */\nexport const AccountDeletionRequestV1Schema = z\n .object({\n schemaVersion: z.literal(1),\n uid: z.string().min(1),\n status: AccountDeletionRequestStatusSchema,\n requestedAt: z.number(),\n // requestedAt + graceDays; the scrub worker queries status='pending' AND\n // scheduledScrubAt <= now (composite index, ttt-prod firestore.indexes.json).\n scheduledScrubAt: z.number(),\n graceDays: z.number(), // recorded for the audit/compliance trail (30 at launch)\n cancelledAt: z.number().optional(),\n // Token-revocation obligation — the request doc IS the durable ledger (BACKEND-302 /\n // QUALITY-104); no separate queue, worker collection, or dead-letter state exists.\n //\n // `tokenRevocationNextAttemptAt` is the DRAIN KEY: present ⇔ the revocation is still\n // OWED. Set to `now` when the request is created; the scheduled worker's revocation\n // drain queries `tokenRevocationNextAttemptAt <= now` (single-field range — deliberately\n // no status clause and no composite index; every terminal transition clears the field,\n // and the drain clears it on any non-active doc it meets, so \"owed\" means exactly\n // \"field present\"). A failed attempt moves it forward (bounded backoff); a successful\n // revoke DELETES it and stamps `tokensRevokedAt` in the same fenced update.\n //\n // The stamp is GENERATION-FENCED on `requestedAt`: the revoker snapshots `requestedAt`\n // before calling Auth and stamps transactionally only if the doc still carries that\n // value with an active status — a delayed revoke from a cancelled request must never\n // mark a newly reopened request satisfied. Revocation is idempotent, so a skipped or\n // lost stamp merely causes one redundant re-revoke.\n tokenRevocationNextAttemptAt: z.number().optional(),\n // When the user's refresh tokens were revoked for THIS request (\"account deletion signs\n // the user out of every session everywhere\"). The callable's immediate revoke is only\n // the accelerator (BACKEND-301); the worker drain above is the guarantee.\n tokensRevokedAt: z.number().optional(),\n scrubStartedAt: z.number().optional(),\n // Why a scrub is parked (e.g. 'blocking safety hold over user data') — kept for\n // the GDPR compliance record so a deferred erasure is explainable.\n parkedReason: z.string().optional(),\n parkedAt: z.number().optional(),\n lastHoldCheckAt: z.number().optional(),\n completedAt: z.number().optional(),\n supersededAt: z.number().optional(),\n supersededReason: z.string().optional(),\n // [C-02] the erasure-vs-hold race fence (see ErasureLeaseV1). Absent until the\n // scrub first acquires the lease; thereafter it carries the live epoch + state.\n erasureLease: ErasureLeaseV1Schema.optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n })\n .strict();\nexport type AccountDeletionRequestV1 = z.infer<typeof AccountDeletionRequestV1Schema>;\n"]}
@@ -4193,6 +4193,7 @@ export declare const COLLECTION_SCHEMAS: {
4193
4193
  scheduledScrubAt: z.ZodNumber;
4194
4194
  graceDays: z.ZodNumber;
4195
4195
  cancelledAt: z.ZodOptional<z.ZodNumber>;
4196
+ tokenRevocationNextAttemptAt: z.ZodOptional<z.ZodNumber>;
4196
4197
  tokensRevokedAt: z.ZodOptional<z.ZodNumber>;
4197
4198
  scrubStartedAt: z.ZodOptional<z.ZodNumber>;
4198
4199
  parkedReason: z.ZodOptional<z.ZodString>;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/registry.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiM7B,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6NkB,CAAC;AAElD,MAAM,MAAM,wBAAwB,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAEvE;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;CAmBiC,CAAC;AAEvE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAOvC,CAAC"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/registry.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAiM7B,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6NkB,CAAC;AAElD,MAAM,MAAM,wBAAwB,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAEvE;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;CAmBiC,CAAC;AAEvE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAOvC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/ttt-core",
3
- "version": "0.79.13",
3
+ "version": "0.79.14",
4
4
  "description": "Core types, Firestore path constants, and shared constants for TTT Productions",
5
5
  "repository": {
6
6
  "type": "git",