@ttt-productions/q-core 0.1.20 → 0.1.21
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/business.js +2 -2
- package/dist/constants/business.js.map +1 -1
- package/dist/constants/media.js +1 -1
- package/dist/constants/media.js.map +1 -1
- package/dist/constants/sports.js +1 -1
- package/dist/constants/sports.js.map +1 -1
- package/dist/constants/telemetry.js +3 -3
- package/dist/constants/telemetry.js.map +1 -1
- package/dist/doc-schemas/admin-notifications.js +3 -3
- package/dist/doc-schemas/admin-notifications.js.map +1 -1
- package/dist/doc-schemas/aggregate-stats.js +3 -3
- package/dist/doc-schemas/aggregate-stats.js.map +1 -1
- package/dist/doc-schemas/atoms.d.ts +1 -1
- package/dist/doc-schemas/atoms.js +3 -3
- package/dist/doc-schemas/atoms.js.map +1 -1
- package/dist/doc-schemas/audit-event.js +2 -2
- package/dist/doc-schemas/audit-event.js.map +1 -1
- package/dist/doc-schemas/firestore-primitives.js +1 -1
- package/dist/doc-schemas/firestore-primitives.js.map +1 -1
- package/dist/doc-schemas/game-location.js +2 -2
- package/dist/doc-schemas/game-location.js.map +1 -1
- package/dist/doc-schemas/game-stat-history.js +1 -1
- package/dist/doc-schemas/game-stat-history.js.map +1 -1
- package/dist/doc-schemas/game-stats.js +6 -6
- package/dist/doc-schemas/game-stats.js.map +1 -1
- package/dist/doc-schemas/league-team.js +4 -4
- package/dist/doc-schemas/league-team.js.map +1 -1
- package/dist/doc-schemas/membership-roster-sync.js +2 -2
- package/dist/doc-schemas/membership-roster-sync.js.map +1 -1
- package/dist/doc-schemas/pending-media.d.ts +6 -6
- package/dist/doc-schemas/publicUser.js +1 -1
- package/dist/doc-schemas/publicUser.js.map +1 -1
- package/dist/doc-schemas/registration-start.js +1 -1
- package/dist/doc-schemas/registration-start.js.map +1 -1
- package/dist/doc-schemas/registry.d.ts +3 -3
- package/dist/doc-schemas/sport-game.js +4 -4
- package/dist/doc-schemas/sport-game.js.map +1 -1
- package/dist/doc-schemas/sport-league.js +1 -1
- package/dist/doc-schemas/sport-league.js.map +1 -1
- package/dist/doc-schemas/stats-operation.js +2 -2
- package/dist/doc-schemas/stats-operation.js.map +1 -1
- package/dist/doc-schemas/status-reconcile-queue.js +1 -1
- package/dist/doc-schemas/status-reconcile-queue.js.map +1 -1
- package/dist/doc-schemas/sweep-state.js +2 -2
- package/dist/doc-schemas/sweep-state.js.map +1 -1
- package/dist/doc-schemas/team-membership.js +1 -1
- package/dist/doc-schemas/team-membership.js.map +1 -1
- package/dist/doc-schemas/user-profile.js +1 -1
- package/dist/doc-schemas/user-profile.js.map +1 -1
- package/dist/doc-schemas/waiver-template.js +1 -1
- package/dist/doc-schemas/waiver-template.js.map +1 -1
- package/dist/doc-schemas/waivers-and-hardware.js +3 -3
- package/dist/doc-schemas/waivers-and-hardware.js.map +1 -1
- package/dist/domain-events/domain-events.js +2 -2
- package/dist/domain-events/domain-events.js.map +1 -1
- package/dist/ids/award-grant-ids.js +1 -1
- package/dist/ids/award-grant-ids.js.map +1 -1
- package/dist/ids/compound-ids.js +1 -1
- package/dist/ids/compound-ids.js.map +1 -1
- package/dist/ids/minted-ids.js +1 -1
- package/dist/ids/minted-ids.js.map +1 -1
- package/dist/ids/notification-ids.js +1 -1
- package/dist/ids/notification-ids.js.map +1 -1
- package/dist/ids/stat-event-ids.d.ts +1 -1
- package/dist/ids/stat-event-ids.js +2 -2
- package/dist/ids/stat-event-ids.js.map +1 -1
- package/dist/ids/stats-operation-ids.js +1 -1
- package/dist/ids/stats-operation-ids.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/input-formats/input-formats.js +1 -1
- package/dist/input-formats/input-formats.js.map +1 -1
- package/dist/media/file-origins.js +1 -1
- package/dist/media/file-origins.js.map +1 -1
- package/dist/media/picture-url.js +1 -1
- package/dist/media/picture-url.js.map +1 -1
- package/dist/migration-console/action-ids.js +1 -1
- package/dist/migration-console/action-ids.js.map +1 -1
- package/dist/migration-console/manifest.js +1 -1
- package/dist/migration-console/manifest.js.map +1 -1
- package/dist/notifications/admin-notification-config.js +1 -1
- package/dist/notifications/admin-notification-config.js.map +1 -1
- package/dist/notifications/occurrences.js +1 -1
- package/dist/notifications/occurrences.js.map +1 -1
- package/dist/paths/collections.js +3 -3
- package/dist/paths/collections.js.map +1 -1
- package/dist/paths/picture-owner-paths.js +1 -1
- package/dist/paths/picture-owner-paths.js.map +1 -1
- package/dist/paths/storage-paths.d.ts +1 -1
- package/dist/paths/storage-paths.js +1 -1
- package/dist/paths/storage-paths.js.map +1 -1
- package/dist/paths/utils.d.ts +1 -1
- package/dist/paths/utils.js +1 -1
- package/dist/paths/utils.js.map +1 -1
- package/dist/schemas/admin-notifications.js +1 -1
- package/dist/schemas/admin-notifications.js.map +1 -1
- package/dist/schemas/app-config.js +1 -1
- package/dist/schemas/app-config.js.map +1 -1
- package/dist/schemas/awards.js +1 -1
- package/dist/schemas/awards.js.map +1 -1
- package/dist/schemas/dead-letters.js +2 -2
- package/dist/schemas/dead-letters.js.map +1 -1
- package/dist/schemas/leagues.js +1 -1
- package/dist/schemas/leagues.js.map +1 -1
- package/dist/schemas/migration-console.js +1 -1
- package/dist/schemas/migration-console.js.map +1 -1
- package/dist/schemas/pictures.js +1 -1
- package/dist/schemas/pictures.js.map +1 -1
- package/dist/schemas/schedules.js +2 -2
- package/dist/schemas/schedules.js.map +1 -1
- package/dist/schemas/scoring.js +1 -1
- package/dist/schemas/scoring.js.map +1 -1
- package/dist/schemas/signed-waivers.js +1 -1
- package/dist/schemas/signed-waivers.js.map +1 -1
- package/dist/schemas/stats.js +6 -6
- package/dist/schemas/stats.js.map +1 -1
- package/dist/schemas/team-joining.js +3 -3
- package/dist/schemas/team-joining.js.map +1 -1
- package/dist/schemas/teams.js +7 -7
- package/dist/schemas/teams.js.map +1 -1
- package/dist/schemas/users.js +3 -3
- package/dist/schemas/users.js.map +1 -1
- package/dist/sports/basketball-scoring.js +4 -4
- package/dist/sports/basketball-scoring.js.map +1 -1
- package/dist/sports/bulk-entry.js +1 -1
- package/dist/sports/bulk-entry.js.map +1 -1
- package/dist/sports/contribution.d.ts +5 -5
- package/dist/sports/contribution.d.ts.map +1 -1
- package/dist/sports/contribution.js +4 -4
- package/dist/sports/contribution.js.map +1 -1
- package/dist/sports/curling-scoring.js +2 -2
- package/dist/sports/curling-scoring.js.map +1 -1
- package/dist/sports/football-scoring.js +2 -2
- package/dist/sports/football-scoring.js.map +1 -1
- package/dist/sports/index.js +1 -1
- package/dist/sports/index.js.map +1 -1
- package/dist/sports/ledger-continuity.js +1 -1
- package/dist/sports/ledger-continuity.js.map +1 -1
- package/dist/sports/registry.js +2 -2
- package/dist/sports/registry.js.map +1 -1
- package/dist/sports/replay.js +1 -1
- package/dist/sports/replay.js.map +1 -1
- package/dist/sports/rollup-check.js +1 -1
- package/dist/sports/rollup-check.js.map +1 -1
- package/dist/sports/score-mirror.js +1 -1
- package/dist/sports/score-mirror.js.map +1 -1
- package/dist/sports/scoring-display.d.ts +1 -1
- package/dist/sports/scoring-display.js +2 -2
- package/dist/sports/scoring-display.js.map +1 -1
- package/dist/sports/scoring.d.ts +5 -5
- package/dist/sports/scoring.d.ts.map +1 -1
- package/dist/sports/scoring.js +2 -2
- package/dist/sports/scoring.js.map +1 -1
- package/dist/sports/sport-adapter.d.ts +3 -3
- package/dist/sports/sport-adapter.d.ts.map +1 -1
- package/dist/sports/sport-adapter.js +2 -2
- package/dist/sports/sport-adapter.js.map +1 -1
- package/dist/sports/store-driver.d.ts +1 -1
- package/dist/sports/store-driver.d.ts.map +1 -1
- package/dist/sports/store-driver.js +2 -2
- package/dist/sports/store-driver.js.map +1 -1
- package/dist/types/audit.js +4 -4
- package/dist/types/audit.js.map +1 -1
- package/dist/types/claims.js +1 -1
- package/dist/types/claims.js.map +1 -1
- package/dist/types/picture-owners.js +1 -1
- package/dist/types/picture-owners.js.map +1 -1
- package/dist/types/schedules.js +1 -1
- package/dist/types/schedules.js.map +1 -1
- package/dist/types/sports.js +2 -2
- package/dist/types/sports.js.map +1 -1
- package/dist/types/stats.js +5 -5
- package/dist/types/stats.js.map +1 -1
- package/dist/types/unions.js +2 -2
- package/dist/types/unions.js.map +1 -1
- package/dist/types/uploads.js +1 -1
- package/dist/types/uploads.js.map +1 -1
- package/dist/upload-variables/sign-hardware-contract-variables.js +1 -1
- package/dist/upload-variables/sign-hardware-contract-variables.js.map +1 -1
- package/dist/upload-variables/sign-waiver-variables.js +1 -1
- package/dist/upload-variables/sign-waiver-variables.js.map +1 -1
- package/dist/utils/account-status.js +1 -1
- package/dist/utils/account-status.js.map +1 -1
- package/dist/utils/app-routes.js +1 -1
- package/dist/utils/app-routes.js.map +1 -1
- package/dist/utils/league-join-warning.js +1 -1
- package/dist/utils/league-join-warning.js.map +1 -1
- package/dist/utils/league-joining.js +1 -1
- package/dist/utils/league-joining.js.map +1 -1
- package/dist/utils/league-mode.js +1 -1
- package/dist/utils/league-mode.js.map +1 -1
- package/dist/utils/team-creation.js +1 -1
- package/dist/utils/team-creation.js.map +1 -1
- package/dist/utils/team-member-actions.js +1 -1
- package/dist/utils/team-member-actions.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-driver.js","sourceRoot":"","sources":["../../src/sports/store-driver.ts"],"names":[],"mappings":"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","sourcesContent":["// The store driver's decision half: what one scoring write does with the batch of events it was\n// sent, given what the game already holds. It owns ids, the sequence, void resolution, and the fold;\n// everything sport-shaped is the adapter's (SPORT-003). The writing core reads the game, the stored\n// events the batch names, and the roster entries it names, hands them here, and writes what comes\n// back — one transaction, all or nothing.\n//\n// An event id is the idempotency key (SPORT-102): an id already stored, or earlier in the batch, is\n// acknowledged when its content matches and never applied again, so re-sending a batch whose first\n// send timed out after committing changes nothing. A void's id is derived from its target, so a\n// second undo of one event is the same document and is acknowledged too.\n\nimport type { GameStatEvent } from '../doc-schemas/game-stats.js';\nimport type { GameStats } from '../doc-schemas/sport-game.js';\nimport { buildStatVoidId } from '../ids/stat-event-ids.js';\nimport type { StatEventSubmission } from '../schemas/scoring.js';\nimport { STAT_EVENT_RECORDER_FIELD_KEYS, STAT_EVENT_SNAPSHOT_FIELD_KEYS } from '../types/stats.js';\nimport type { RecordedStatEventOutcome, StatEventRefusalCode } from '../types/stats.js';\nimport { foldStatEvent, withGameTeamLines } from './replay.js';\nimport {\n isSportStatEventIn,\n isStatCorrection,\n isStatVoid,\n type StatEventBody,\n type StatEventRoster,\n} from './scoring.js';\nimport type { AnySportAdapter, GameTeamIds } from './sport-adapter.js';\n\n/** The document id a submission is stored at. */\nexport function statEventSubmissionId(submission: StatEventSubmission): string {\n return isStatVoid(submission) ? buildStatVoidId(submission.targetEventId) : submission.eventId;\n}\n\n/**\n * The ids a batch reads before it decides anything: every submission's own id, and every void's\n * target — the driver needs the stored document at each, or knows none is stored. A correction's is\n * never read: the driver refuses one before it looks at the store.\n */\nexport function statEventIdsToRead(submissions: readonly StatEventSubmission[]): string[] {\n const ids = new Set<string>();\n for (const submission of submissions) {\n if (isStatCorrection(submission)) continue;\n ids.add(statEventSubmissionId(submission));\n if (isStatVoid(submission)) ids.add(submission.targetEventId);\n }\n return [...ids];\n}\n\n/** An event the batch stores now: its id, its place in the replay, and every field its caller sent. */\nexport interface AcceptedStatEvent {\n readonly eventId: string;\n readonly sequence: number;\n /** The document's fields but the recorder facts, which the writing core stamps (ARCH-106). */\n readonly fields: Readonly<Record<string, unknown>>;\n}\n\nexport interface RecordedStatEventResult {\n readonly eventId: string;\n readonly outcome: RecordedStatEventOutcome;\n readonly sequence: number;\n}\n\nexport type StatEventBatchDecision =\n | {\n readonly ok: true;\n /** The rollup after the batch — unchanged when every event was already recorded. */\n readonly stats: GameStats;\n readonly statEventSequence: number;\n /** Each submission's result, in the order sent. */\n readonly results: readonly RecordedStatEventResult[];\n /** The events to create, in sequence order; empty when every event was already recorded. */\n readonly accepted: readonly AcceptedStatEvent[];\n }\n | {\n readonly ok: false;\n readonly code: StatEventRefusalCode;\n /** The first submission refused; nothing of the batch is written. */\n readonly eventId: string;\n };\n\nexport interface StatEventBatch {\n readonly adapter: AnySportAdapter;\n readonly game: GameTeamIds & { readonly stats: GameStats; readonly statEventSequence: number };\n /** The game's teams and the roster entries the batch names that exist. */\n readonly roster: StatEventRoster;\n readonly submissions: readonly StatEventSubmission[];\n /** The stored event at an id `statEventIdsToRead` named, or `undefined` where none is stored. */\n readonly storedEvent: (eventId: string) => GameStatEvent | undefined;\n}\n\n// The fields of a stored event the writing core derives, which a caller's re-send never carries.\nconst DERIVED_FIELDS: ReadonlySet<string> = new Set([\n ...STAT_EVENT_RECORDER_FIELD_KEYS,\n ...STAT_EVENT_SNAPSHOT_FIELD_KEYS,\n]);\n\nfunction callerFields(event: Readonly<Record<string, unknown>>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(event).filter(\n ([field, value]) => !DERIVED_FIELDS.has(field) && value !== undefined,\n ),\n );\n}\n\nfunction sameFields(\n left: Readonly<Record<string, unknown>>,\n right: Readonly<Record<string, unknown>>,\n): boolean {\n const leftFields = callerFields(left);\n const rightFields = callerFields(right);\n const keys = Object.keys(leftFields);\n return (\n keys.length === Object.keys(rightFields).length &&\n keys.every((key) => Object.is(leftFields[key], rightFields[key]))\n );\n}\n\n/**\n * Whether a submission is the event already held at its id. A void is the same void when it names\n * the same target; a sport event only when every field its caller supplies is the same.\n */\nfunction isSameEvent(\n submission: StatEventSubmission,\n held: Readonly<Record<string, unknown>>,\n): boolean {\n if (isStatVoid(submission))\n return isStatVoid(held as StatEventBody) && held.targetEventId === submission.targetEventId;\n return sameFields(submission as Readonly<Record<string, unknown>>, held);\n}\n\n/** Whether any counter, or any recorded round, of any line is below zero. */\nfunction holdsNegativeValue(stats: GameStats): boolean {\n const lines = [...Object.values(stats.teamStats), ...Object.values(stats.playerStats)] as Record<\n string,\n unknown\n >[];\n return lines.some((line) =>\n Object.values(line).some((value) =>\n Array.isArray(value)\n ? value.some((slot) => typeof slot === 'number' && slot < 0)\n : typeof value === 'number' && value < 0,\n ),\n );\n}\n\n/** The stored fields of a new event: the void's derived id, or the caller's own id and fields. */\nfunction acceptedFields(\n submission: StatEventSubmission,\n eventId: string,\n sequence: number,\n): Record<string, unknown> {\n return { ...callerFields(submission as Readonly<Record<string, unknown>>), eventId, sequence };\n}\n\n/**\n * Decide one scoring write. Every submission in order, against a running rollup that starts from\n * the stored one with a team line for each of the game's teams:\n *\n * - a correction → refused; only the game-reconcile core appends one;\n * - an id already stored, or earlier in the batch → acknowledged when it is the same event, and\n * refused (`eventIdConflict`) when it is not;\n * - a new sport event → the adapter validates it and applies it, and it takes the next sequence;\n * - a new void → its target, stored or earlier in the batch, must be one of the sport's events; the\n * adapter undoes it, and it takes the next sequence. A void that would leave a stat below zero —\n * the target's field moved down by a later edit — is refused (`undoBelowZero`).\n *\n * The first refusal refuses the whole batch.\n */\nexport function decideStatEventBatch(batch: StatEventBatch): StatEventBatchDecision {\n const { adapter, game, roster, submissions, storedEvent } = batch;\n let stats = withGameTeamLines(adapter, game.stats, game);\n let sequence = game.statEventSequence;\n const results: RecordedStatEventResult[] = [];\n const accepted: AcceptedStatEvent[] = [];\n // Every event the batch has placed so far — stored or new — by id, with the sequence it holds.\n const placed = new Map<\n string,\n { readonly event: Readonly<Record<string, unknown>>; readonly sequence: number }\n >();\n\n for (const submission of submissions) {\n const eventId = statEventSubmissionId(submission);\n const refuse = (code: StatEventRefusalCode): StatEventBatchDecision => ({\n ok: false,\n code,\n eventId,\n });\n\n if (isStatCorrection(submission)) return refuse('correctionNotAccepted');\n\n const held =\n placed.get(eventId) ??\n (() => {\n const stored = storedEvent(eventId);\n return stored === undefined\n ? undefined\n : { event: stored as Readonly<Record<string, unknown>>, sequence: stored.sequence };\n })();\n if (held !== undefined) {\n if (!isSameEvent(submission, held.event)) return refuse('eventIdConflict');\n placed.set(eventId, held);\n results.push({ eventId, outcome: 'alreadyRecorded', sequence: held.sequence });\n continue;\n }\n\n if (isStatVoid(submission)) {\n const target =\n placed.get(submission.targetEventId)?.event ?? storedEvent(submission.targetEventId);\n if (!isSportStatEventIn(adapter.eventTypes, target as StatEventBody | undefined)) {\n return refuse('voidTargetNotSportEvent');\n }\n const next = foldStatEvent(adapter, stats, submission, () => target as StatEventBody);\n if (holdsNegativeValue(next)) return refuse('undoBelowZero');\n stats = next;\n } else {\n const verdict = adapter.validate(stats, submission, roster);\n if (!verdict.ok) return refuse(verdict.code);\n stats = foldStatEvent(adapter, stats, submission, () => undefined);\n }\n\n sequence += 1;\n const fields = acceptedFields(submission, eventId, sequence);\n accepted.push({ eventId, sequence, fields });\n placed.set(eventId, { event: fields, sequence });\n results.push({ eventId, outcome: 'recorded', sequence });\n }\n\n return { ok: true, stats, statEventSequence: sequence, results, accepted };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"store-driver.js","sourceRoot":"","sources":["../../src/sports/store-driver.ts"],"names":[],"mappings":"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","sourcesContent":["// The store driver's decision half: what one scoring write does with the batch of events it was\n// sent, given what the game already holds. It owns ids, the sequence, void resolution, and the fold;\n// everything sport-shaped is the adapter's (RULE-QS-SPORT-903). The writing core reads the game, the stored\n// events the batch names, and the roster entries it names, hands them here, and writes what comes\n// back — one transaction, all or nothing.\n//\n// An event id is the idempotency key (RULE-QS-SPORT-912): an id already stored, or earlier in the batch, is\n// acknowledged when its content matches and never applied again, so re-sending a batch whose first\n// send timed out after committing changes nothing. A void's id is derived from its target, so a\n// second undo of one event is the same document and is acknowledged too.\n\nimport type { GameStatEvent } from '../doc-schemas/game-stats.js';\nimport type { GameStats } from '../doc-schemas/sport-game.js';\nimport { buildStatVoidId } from '../ids/stat-event-ids.js';\nimport type { StatEventSubmission } from '../schemas/scoring.js';\nimport { STAT_EVENT_RECORDER_FIELD_KEYS, STAT_EVENT_SNAPSHOT_FIELD_KEYS } from '../types/stats.js';\nimport type { RecordedStatEventOutcome, StatEventRefusalCode } from '../types/stats.js';\nimport { foldStatEvent, withGameTeamLines } from './replay.js';\nimport {\n isSportStatEventIn,\n isStatCorrection,\n isStatVoid,\n type StatEventBody,\n type StatEventRoster,\n} from './scoring.js';\nimport type { AnySportAdapter, GameTeamIds } from './sport-adapter.js';\n\n/** The document id a submission is stored at. */\nexport function statEventSubmissionId(submission: StatEventSubmission): string {\n return isStatVoid(submission) ? buildStatVoidId(submission.targetEventId) : submission.eventId;\n}\n\n/**\n * The ids a batch reads before it decides anything: every submission's own id, and every void's\n * target — the driver needs the stored document at each, or knows none is stored. A correction's is\n * never read: the driver refuses one before it looks at the store.\n */\nexport function statEventIdsToRead(submissions: readonly StatEventSubmission[]): string[] {\n const ids = new Set<string>();\n for (const submission of submissions) {\n if (isStatCorrection(submission)) continue;\n ids.add(statEventSubmissionId(submission));\n if (isStatVoid(submission)) ids.add(submission.targetEventId);\n }\n return [...ids];\n}\n\n/** An event the batch stores now: its id, its place in the replay, and every field its caller sent. */\nexport interface AcceptedStatEvent {\n readonly eventId: string;\n readonly sequence: number;\n /** The document's fields but the recorder facts, which the writing core stamps (RULE-STD-ARCH-106). */\n readonly fields: Readonly<Record<string, unknown>>;\n}\n\nexport interface RecordedStatEventResult {\n readonly eventId: string;\n readonly outcome: RecordedStatEventOutcome;\n readonly sequence: number;\n}\n\nexport type StatEventBatchDecision =\n | {\n readonly ok: true;\n /** The rollup after the batch — unchanged when every event was already recorded. */\n readonly stats: GameStats;\n readonly statEventSequence: number;\n /** Each submission's result, in the order sent. */\n readonly results: readonly RecordedStatEventResult[];\n /** The events to create, in sequence order; empty when every event was already recorded. */\n readonly accepted: readonly AcceptedStatEvent[];\n }\n | {\n readonly ok: false;\n readonly code: StatEventRefusalCode;\n /** The first submission refused; nothing of the batch is written. */\n readonly eventId: string;\n };\n\nexport interface StatEventBatch {\n readonly adapter: AnySportAdapter;\n readonly game: GameTeamIds & { readonly stats: GameStats; readonly statEventSequence: number };\n /** The game's teams and the roster entries the batch names that exist. */\n readonly roster: StatEventRoster;\n readonly submissions: readonly StatEventSubmission[];\n /** The stored event at an id `statEventIdsToRead` named, or `undefined` where none is stored. */\n readonly storedEvent: (eventId: string) => GameStatEvent | undefined;\n}\n\n// The fields of a stored event the writing core derives, which a caller's re-send never carries.\nconst DERIVED_FIELDS: ReadonlySet<string> = new Set([\n ...STAT_EVENT_RECORDER_FIELD_KEYS,\n ...STAT_EVENT_SNAPSHOT_FIELD_KEYS,\n]);\n\nfunction callerFields(event: Readonly<Record<string, unknown>>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(event).filter(\n ([field, value]) => !DERIVED_FIELDS.has(field) && value !== undefined,\n ),\n );\n}\n\nfunction sameFields(\n left: Readonly<Record<string, unknown>>,\n right: Readonly<Record<string, unknown>>,\n): boolean {\n const leftFields = callerFields(left);\n const rightFields = callerFields(right);\n const keys = Object.keys(leftFields);\n return (\n keys.length === Object.keys(rightFields).length &&\n keys.every((key) => Object.is(leftFields[key], rightFields[key]))\n );\n}\n\n/**\n * Whether a submission is the event already held at its id. A void is the same void when it names\n * the same target; a sport event only when every field its caller supplies is the same.\n */\nfunction isSameEvent(\n submission: StatEventSubmission,\n held: Readonly<Record<string, unknown>>,\n): boolean {\n if (isStatVoid(submission))\n return isStatVoid(held as StatEventBody) && held.targetEventId === submission.targetEventId;\n return sameFields(submission as Readonly<Record<string, unknown>>, held);\n}\n\n/** Whether any counter, or any recorded round, of any line is below zero. */\nfunction holdsNegativeValue(stats: GameStats): boolean {\n const lines = [...Object.values(stats.teamStats), ...Object.values(stats.playerStats)] as Record<\n string,\n unknown\n >[];\n return lines.some((line) =>\n Object.values(line).some((value) =>\n Array.isArray(value)\n ? value.some((slot) => typeof slot === 'number' && slot < 0)\n : typeof value === 'number' && value < 0,\n ),\n );\n}\n\n/** The stored fields of a new event: the void's derived id, or the caller's own id and fields. */\nfunction acceptedFields(\n submission: StatEventSubmission,\n eventId: string,\n sequence: number,\n): Record<string, unknown> {\n return { ...callerFields(submission as Readonly<Record<string, unknown>>), eventId, sequence };\n}\n\n/**\n * Decide one scoring write. Every submission in order, against a running rollup that starts from\n * the stored one with a team line for each of the game's teams:\n *\n * - a correction → refused; only the game-reconcile core appends one;\n * - an id already stored, or earlier in the batch → acknowledged when it is the same event, and\n * refused (`eventIdConflict`) when it is not;\n * - a new sport event → the adapter validates it and applies it, and it takes the next sequence;\n * - a new void → its target, stored or earlier in the batch, must be one of the sport's events; the\n * adapter undoes it, and it takes the next sequence. A void that would leave a stat below zero —\n * the target's field moved down by a later edit — is refused (`undoBelowZero`).\n *\n * The first refusal refuses the whole batch.\n */\nexport function decideStatEventBatch(batch: StatEventBatch): StatEventBatchDecision {\n const { adapter, game, roster, submissions, storedEvent } = batch;\n let stats = withGameTeamLines(adapter, game.stats, game);\n let sequence = game.statEventSequence;\n const results: RecordedStatEventResult[] = [];\n const accepted: AcceptedStatEvent[] = [];\n // Every event the batch has placed so far — stored or new — by id, with the sequence it holds.\n const placed = new Map<\n string,\n { readonly event: Readonly<Record<string, unknown>>; readonly sequence: number }\n >();\n\n for (const submission of submissions) {\n const eventId = statEventSubmissionId(submission);\n const refuse = (code: StatEventRefusalCode): StatEventBatchDecision => ({\n ok: false,\n code,\n eventId,\n });\n\n if (isStatCorrection(submission)) return refuse('correctionNotAccepted');\n\n const held =\n placed.get(eventId) ??\n (() => {\n const stored = storedEvent(eventId);\n return stored === undefined\n ? undefined\n : { event: stored as Readonly<Record<string, unknown>>, sequence: stored.sequence };\n })();\n if (held !== undefined) {\n if (!isSameEvent(submission, held.event)) return refuse('eventIdConflict');\n placed.set(eventId, held);\n results.push({ eventId, outcome: 'alreadyRecorded', sequence: held.sequence });\n continue;\n }\n\n if (isStatVoid(submission)) {\n const target =\n placed.get(submission.targetEventId)?.event ?? storedEvent(submission.targetEventId);\n if (!isSportStatEventIn(adapter.eventTypes, target as StatEventBody | undefined)) {\n return refuse('voidTargetNotSportEvent');\n }\n const next = foldStatEvent(adapter, stats, submission, () => target as StatEventBody);\n if (holdsNegativeValue(next)) return refuse('undoBelowZero');\n stats = next;\n } else {\n const verdict = adapter.validate(stats, submission, roster);\n if (!verdict.ok) return refuse(verdict.code);\n stats = foldStatEvent(adapter, stats, submission, () => undefined);\n }\n\n sequence += 1;\n const fields = acceptedFields(submission, eventId, sequence);\n accepted.push({ eventId, sequence, fields });\n placed.set(eventId, { event: fields, sequence });\n results.push({ eventId, outcome: 'recorded', sequence });\n }\n\n return { ok: true, stats, statEventSequence: sequence, results, accepted };\n}\n"]}
|
package/dist/types/audit.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// The audit vocabulary: the closed event-type union (BACKEND-202) and how an actor was acting
|
|
2
|
-
// (BACKEND-205). The document schema is in ../doc-schemas/audit-event.ts.
|
|
1
|
+
// The audit vocabulary: the closed event-type union (RULE-STD-BACKEND-202) and how an actor was acting
|
|
2
|
+
// (RULE-STD-BACKEND-205). The document schema is in ../doc-schemas/audit-event.ts.
|
|
3
3
|
//
|
|
4
4
|
// The union is closed: a new sensitive action adds its event types here, in the same change
|
|
5
|
-
// (BACKEND-202).
|
|
5
|
+
// (RULE-STD-BACKEND-202).
|
|
6
6
|
export const AUDIT_EVENT_TYPE_KEYS = [
|
|
7
7
|
// Accounts
|
|
8
8
|
'user.accountRegistered',
|
|
@@ -130,7 +130,7 @@ export const AUDIT_EVENT_TYPE_KEYS = [
|
|
|
130
130
|
'system.manualIntervention',
|
|
131
131
|
// The migration console — one page of a cutover action run, with what it read, wrote, and found;
|
|
132
132
|
// the documents an action core wrote and removed, committed in the same batch or transaction as
|
|
133
|
-
// those writes (its action id, operation id, and document ids only — BACKEND-203); a product
|
|
133
|
+
// those writes (its action id, operation id, and document ids only — RULE-STD-BACKEND-203); a product
|
|
134
134
|
// control's run recorded once its evidence checked; an operator checkpoint recorded with its
|
|
135
135
|
// evidence; and the cutover, after which the product owns every destination
|
|
136
136
|
'migrationAction.pageRun',
|
package/dist/types/audit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/types/audit.ts"],"names":[],"mappings":"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","sourcesContent":["// The audit vocabulary: the closed event-type union (BACKEND-202) and how an actor was acting\n// (BACKEND-205). The document schema is in ../doc-schemas/audit-event.ts.\n//\n// The union is closed: a new sensitive action adds its event types here, in the same change\n// (BACKEND-202).\n\nimport type { SystemRole } from './unions.js';\nimport { CAPTAIN_TEAM_ROLES } from './unions.js';\n\nexport const AUDIT_EVENT_TYPE_KEYS = [\n // Accounts\n 'user.accountRegistered',\n 'user.displayNameChanged',\n // The scheduled sweep deleted a sign-in account that never finished registering (no profile)\n 'user.abandonedRegistrationDeleted',\n // Account status — an admin banned an account or lifted its ban\n 'user.accountBanned',\n 'user.accountUnbanned',\n // Global roles — the policy decision (callable) and the claim propagation (trigger)\n 'admin.systemRoleGranted',\n 'admin.systemRoleRevoked',\n 'admin.systemRoleClaimSynced',\n // App configuration — the operational levers on `_appConfig/app`, and the landing page copy\n 'appConfig.updated',\n 'landingPage.updated',\n // Leagues — created, settings edited, status moved, mode switched\n 'league.created',\n 'league.updated',\n 'league.statusChanged',\n 'league.modeSwitched',\n // Waiver templates — created, a new wording published, retired or deleted\n 'waiverTemplate.created',\n 'waiverTemplate.versionPublished',\n 'waiverTemplate.retired',\n 'waiverTemplate.deleted',\n // Game locations\n 'gameLocation.created',\n 'gameLocation.updated',\n 'gameLocation.deleted',\n // Pictures — published to a gallery or a slot by the picture processor (attributed to the admin\n // who uploaded it), and ordered, featured, and removed by the admin picture callables\n 'picture.added',\n 'picture.replaced',\n 'picture.moved',\n 'picture.featuredChanged',\n 'picture.removed',\n // Awards — an award created by its first badge's publication, its badge replaced, the award\n // deleted once nobody holds it, and an award granted to or revoked from one account\n 'award.created',\n 'award.badgeReplaced',\n 'award.deleted',\n 'award.granted',\n 'award.revoked',\n // Hardware contracts — a loan created for a referee, signed by them, its equipment returned, and a\n // contract never signed deleted\n 'hardwareLoanContract.created',\n 'hardwareLoanContract.signed',\n 'hardwareLoanContract.returned',\n 'hardwareLoanContract.deleted',\n // Teams — created with its captain, a ghost player added, a team's failed roster work retried\n 'leagueTeam.created',\n 'ghostPlayer.created',\n 'teamRoster.syncRetried',\n // Team management — a member promoted to co-captain or demoted to player, the captain changed by\n // an admin, the team's name or type edited by an admin, and its contact phone set by an admin\n 'teamMembership.roleChanged',\n 'leagueTeam.captainChanged',\n 'leagueTeam.updated',\n 'leagueTeamContact.updated',\n // Exits — a membership removed, a never-played ghost removed, a ghost linked by either link, and a\n // never-played team deleted; each targets what it deleted, which the migration's live\n // verifications read as proof the product removed it\n 'teamMembership.removed',\n 'ghostPlayer.removed',\n 'ghostPlayer.linked',\n 'ghostPlayer.closedLeagueLinked',\n 'leagueTeam.deleted',\n // A ghost's removal stopped part-way because the ghost came to have played: the games it held are\n // released, and the finished-game entries it had already taken off are named\n 'ghostPlayer.removalStopped',\n // Joining a team — an invitation sent, withdrawn, accepted, or declined; a join request sent,\n // withdrawn, accepted, or rejected; a free-agent signup made, withdrawn, or answered by an admin\n // placing the player on a team\n 'teamInvitation.created',\n 'teamInvitation.cancelled',\n 'teamInvitation.accepted',\n 'teamInvitation.rejected',\n 'teamJoinRequest.created',\n 'teamJoinRequest.cancelled',\n 'teamJoinRequest.accepted',\n 'teamJoinRequest.rejected',\n 'leagueFreeAgent.created',\n 'leagueFreeAgent.deleted',\n 'leagueFreeAgent.assigned',\n // Signed waivers — a legal record, signed by its subject or witnessed for a ghost\n 'signedWaiver.created',\n // Schedules — a week created with its games or its shared fields edited; one game added, edited\n // (moved, rescheduled, or its teams replaced), or deleted with its events and roster\n 'scheduleWeek.created',\n 'scheduleWeek.updated',\n 'sportGame.created',\n 'sportGame.updated',\n 'sportGame.deleted',\n // Live scoring — a scoring write refused its caller's authority (a click writes no success event:\n // the stat event document is its own record), a roster entry marked absent or present, a\n // scorer's note on one person changed, and the jump-ball possession arrow moved\n 'sportGame.statEventsRejected',\n 'sportGame.absenceChanged',\n 'sportGame.memoUpdated',\n 'sportGame.jumpBallChanged',\n // Finalizing — a game finalized, its numbers made permanent in every derived destination, and an\n // admin's reopening of a finalized game, which takes them back out\n 'sportGame.finalized',\n 'sportGame.reopened',\n // Fix stats — a game's numbers corrected (targets, or the stored numbers kept) or restored from\n // its events; a derived aggregate rebuilt; and a person's pre-Q-Sports baseline written\n 'sportGame.statsCorrected',\n 'sportGame.statsRecalculated',\n 'stats.aggregateRecalculated',\n 'stats.historicalStatsUpdated',\n // A stats check ran to its end: its scope, its summary, and its counts by kind.\n 'stats.validationRun',\n // An admin deleted a stats check's report: its id, scope, summary, and counts by kind.\n 'stats.validationReportDeleted',\n // The migration's placement of a recorded stat line no roster entry or play could place: the\n // admin names the team, and the game's copy places the line there\n 'stats.unrosteredStatLineResolved',\n // Admin notifications — a shared card archived, which takes it off every admin's list; and an\n // admin's archive-all decision, recorded once when the job is written, with the request's origin\n 'adminNotification.archived',\n 'adminNotification.archiveAllRequested',\n // An operator's manual intervention in a durable pipeline — a dead-lettered row put back to work,\n // or a refused attempt at one — with the reason the operator gave\n 'system.manualIntervention',\n // The migration console — one page of a cutover action run, with what it read, wrote, and found;\n // the documents an action core wrote and removed, committed in the same batch or transaction as\n // those writes (its action id, operation id, and document ids only — BACKEND-203); a product\n // control's run recorded once its evidence checked; an operator checkpoint recorded with its\n // evidence; and the cutover, after which the product owns every destination\n 'migrationAction.pageRun',\n 'migrationAction.writesCommitted',\n 'migrationAction.controlRecorded',\n 'migrationAction.checkpointRecorded',\n 'migrationConsole.cutoverRecorded',\n] as const;\nexport type AuditEventType = (typeof AUDIT_EVENT_TYPE_KEYS)[number];\n\n// The two ways a ghost is linked to an account — the normal link and the closed-league link — each\n// committing its own event over the one artifact-moving core.\nexport const GHOST_LINK_AUDIT_EVENT_TYPE_KEYS = [\n 'ghostPlayer.linked',\n 'ghostPlayer.closedLeagueLinked',\n] as const satisfies readonly AuditEventType[];\nexport type GhostLinkAuditEventType = (typeof GHOST_LINK_AUDIT_EVENT_TYPE_KEYS)[number];\n\n// How the actor was acting for the write — never merely which authorities they happen to hold. It is\n// orthogonal to the event type: one event type is produced under several modes, and the mode is what\n// tells an ordinary action from an admin override.\n// user a signed-in account acting on its own behalf\n// teamManager a captain or co-captain acting through their team's membership permissions\n// adminReview an admin or referee doing admin work that no team permission covers\n// adminOverride an admin or referee superseding the team permission a normal entry checks\n// system backend automation with no human caller\nexport const AUDIT_ACTOR_MODE_KEYS = [\n 'user',\n 'teamManager',\n 'adminReview',\n 'adminOverride',\n 'system',\n] as const;\nexport type AuditActorMode = (typeof AUDIT_ACTOR_MODE_KEYS)[number];\n\nexport const AUDIT_ADMIN_ACTOR_MODE_KEYS = [\n 'adminReview',\n 'adminOverride',\n] as const satisfies readonly AuditActorMode[];\nexport type AuditAdminActorMode = (typeof AUDIT_ADMIN_ACTOR_MODE_KEYS)[number];\n\nexport const AUDIT_NON_ADMIN_ACTOR_MODE_KEYS = [\n 'user',\n 'teamManager',\n 'system',\n] as const satisfies readonly AuditActorMode[];\nexport type AuditNonAdminActorMode = (typeof AUDIT_NON_ADMIN_ACTOR_MODE_KEYS)[number];\n\nexport const AUDIT_SYSTEM_REASON_KEYS = ['trigger', 'scheduledJob', 'migration'] as const;\nexport type AuditSystemReason = (typeof AUDIT_SYSTEM_REASON_KEYS)[number];\n\nexport type CaptainTeamRole = (typeof CAPTAIN_TEAM_ROLES)[number];\n\n// `isAdmin` is metadata only: it records that the caller's token carried a global-role claim (admin\n// or referee) when they acted, and grants nothing. `systemRole` is required on the admin modes and\n// forbidden on the others, so an admin action is never recorded without the authority it used and a\n// non-admin action never carries one.\nexport type AuditActor =\n | { uid: string | null; isAdmin: boolean; actorMode: AuditNonAdminActorMode; systemRole?: never }\n | {\n uid: string | null;\n isAdmin: boolean;\n actorMode: AuditAdminActorMode;\n systemRole: SystemRole;\n };\n\nexport interface AuditTarget {\n // The user the action was performed on, when there is one.\n uid: string | null;\n // The slash path of the document the action changed, when there is one.\n ref: string | null;\n}\n\nexport const AUDIT_RESULT_KEYS = ['success', 'failure'] as const;\nexport type AuditResult = (typeof AUDIT_RESULT_KEYS)[number];\n"]}
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/types/audit.ts"],"names":[],"mappings":"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","sourcesContent":["// The audit vocabulary: the closed event-type union (RULE-STD-BACKEND-202) and how an actor was acting\n// (RULE-STD-BACKEND-205). The document schema is in ../doc-schemas/audit-event.ts.\n//\n// The union is closed: a new sensitive action adds its event types here, in the same change\n// (RULE-STD-BACKEND-202).\n\nimport type { SystemRole } from './unions.js';\nimport { CAPTAIN_TEAM_ROLES } from './unions.js';\n\nexport const AUDIT_EVENT_TYPE_KEYS = [\n // Accounts\n 'user.accountRegistered',\n 'user.displayNameChanged',\n // The scheduled sweep deleted a sign-in account that never finished registering (no profile)\n 'user.abandonedRegistrationDeleted',\n // Account status — an admin banned an account or lifted its ban\n 'user.accountBanned',\n 'user.accountUnbanned',\n // Global roles — the policy decision (callable) and the claim propagation (trigger)\n 'admin.systemRoleGranted',\n 'admin.systemRoleRevoked',\n 'admin.systemRoleClaimSynced',\n // App configuration — the operational levers on `_appConfig/app`, and the landing page copy\n 'appConfig.updated',\n 'landingPage.updated',\n // Leagues — created, settings edited, status moved, mode switched\n 'league.created',\n 'league.updated',\n 'league.statusChanged',\n 'league.modeSwitched',\n // Waiver templates — created, a new wording published, retired or deleted\n 'waiverTemplate.created',\n 'waiverTemplate.versionPublished',\n 'waiverTemplate.retired',\n 'waiverTemplate.deleted',\n // Game locations\n 'gameLocation.created',\n 'gameLocation.updated',\n 'gameLocation.deleted',\n // Pictures — published to a gallery or a slot by the picture processor (attributed to the admin\n // who uploaded it), and ordered, featured, and removed by the admin picture callables\n 'picture.added',\n 'picture.replaced',\n 'picture.moved',\n 'picture.featuredChanged',\n 'picture.removed',\n // Awards — an award created by its first badge's publication, its badge replaced, the award\n // deleted once nobody holds it, and an award granted to or revoked from one account\n 'award.created',\n 'award.badgeReplaced',\n 'award.deleted',\n 'award.granted',\n 'award.revoked',\n // Hardware contracts — a loan created for a referee, signed by them, its equipment returned, and a\n // contract never signed deleted\n 'hardwareLoanContract.created',\n 'hardwareLoanContract.signed',\n 'hardwareLoanContract.returned',\n 'hardwareLoanContract.deleted',\n // Teams — created with its captain, a ghost player added, a team's failed roster work retried\n 'leagueTeam.created',\n 'ghostPlayer.created',\n 'teamRoster.syncRetried',\n // Team management — a member promoted to co-captain or demoted to player, the captain changed by\n // an admin, the team's name or type edited by an admin, and its contact phone set by an admin\n 'teamMembership.roleChanged',\n 'leagueTeam.captainChanged',\n 'leagueTeam.updated',\n 'leagueTeamContact.updated',\n // Exits — a membership removed, a never-played ghost removed, a ghost linked by either link, and a\n // never-played team deleted; each targets what it deleted, which the migration's live\n // verifications read as proof the product removed it\n 'teamMembership.removed',\n 'ghostPlayer.removed',\n 'ghostPlayer.linked',\n 'ghostPlayer.closedLeagueLinked',\n 'leagueTeam.deleted',\n // A ghost's removal stopped part-way because the ghost came to have played: the games it held are\n // released, and the finished-game entries it had already taken off are named\n 'ghostPlayer.removalStopped',\n // Joining a team — an invitation sent, withdrawn, accepted, or declined; a join request sent,\n // withdrawn, accepted, or rejected; a free-agent signup made, withdrawn, or answered by an admin\n // placing the player on a team\n 'teamInvitation.created',\n 'teamInvitation.cancelled',\n 'teamInvitation.accepted',\n 'teamInvitation.rejected',\n 'teamJoinRequest.created',\n 'teamJoinRequest.cancelled',\n 'teamJoinRequest.accepted',\n 'teamJoinRequest.rejected',\n 'leagueFreeAgent.created',\n 'leagueFreeAgent.deleted',\n 'leagueFreeAgent.assigned',\n // Signed waivers — a legal record, signed by its subject or witnessed for a ghost\n 'signedWaiver.created',\n // Schedules — a week created with its games or its shared fields edited; one game added, edited\n // (moved, rescheduled, or its teams replaced), or deleted with its events and roster\n 'scheduleWeek.created',\n 'scheduleWeek.updated',\n 'sportGame.created',\n 'sportGame.updated',\n 'sportGame.deleted',\n // Live scoring — a scoring write refused its caller's authority (a click writes no success event:\n // the stat event document is its own record), a roster entry marked absent or present, a\n // scorer's note on one person changed, and the jump-ball possession arrow moved\n 'sportGame.statEventsRejected',\n 'sportGame.absenceChanged',\n 'sportGame.memoUpdated',\n 'sportGame.jumpBallChanged',\n // Finalizing — a game finalized, its numbers made permanent in every derived destination, and an\n // admin's reopening of a finalized game, which takes them back out\n 'sportGame.finalized',\n 'sportGame.reopened',\n // Fix stats — a game's numbers corrected (targets, or the stored numbers kept) or restored from\n // its events; a derived aggregate rebuilt; and a person's pre-Q-Sports baseline written\n 'sportGame.statsCorrected',\n 'sportGame.statsRecalculated',\n 'stats.aggregateRecalculated',\n 'stats.historicalStatsUpdated',\n // A stats check ran to its end: its scope, its summary, and its counts by kind.\n 'stats.validationRun',\n // An admin deleted a stats check's report: its id, scope, summary, and counts by kind.\n 'stats.validationReportDeleted',\n // The migration's placement of a recorded stat line no roster entry or play could place: the\n // admin names the team, and the game's copy places the line there\n 'stats.unrosteredStatLineResolved',\n // Admin notifications — a shared card archived, which takes it off every admin's list; and an\n // admin's archive-all decision, recorded once when the job is written, with the request's origin\n 'adminNotification.archived',\n 'adminNotification.archiveAllRequested',\n // An operator's manual intervention in a durable pipeline — a dead-lettered row put back to work,\n // or a refused attempt at one — with the reason the operator gave\n 'system.manualIntervention',\n // The migration console — one page of a cutover action run, with what it read, wrote, and found;\n // the documents an action core wrote and removed, committed in the same batch or transaction as\n // those writes (its action id, operation id, and document ids only — RULE-STD-BACKEND-203); a product\n // control's run recorded once its evidence checked; an operator checkpoint recorded with its\n // evidence; and the cutover, after which the product owns every destination\n 'migrationAction.pageRun',\n 'migrationAction.writesCommitted',\n 'migrationAction.controlRecorded',\n 'migrationAction.checkpointRecorded',\n 'migrationConsole.cutoverRecorded',\n] as const;\nexport type AuditEventType = (typeof AUDIT_EVENT_TYPE_KEYS)[number];\n\n// The two ways a ghost is linked to an account — the normal link and the closed-league link — each\n// committing its own event over the one artifact-moving core.\nexport const GHOST_LINK_AUDIT_EVENT_TYPE_KEYS = [\n 'ghostPlayer.linked',\n 'ghostPlayer.closedLeagueLinked',\n] as const satisfies readonly AuditEventType[];\nexport type GhostLinkAuditEventType = (typeof GHOST_LINK_AUDIT_EVENT_TYPE_KEYS)[number];\n\n// How the actor was acting for the write — never merely which authorities they happen to hold. It is\n// orthogonal to the event type: one event type is produced under several modes, and the mode is what\n// tells an ordinary action from an admin override.\n// user a signed-in account acting on its own behalf\n// teamManager a captain or co-captain acting through their team's membership permissions\n// adminReview an admin or referee doing admin work that no team permission covers\n// adminOverride an admin or referee superseding the team permission a normal entry checks\n// system backend automation with no human caller\nexport const AUDIT_ACTOR_MODE_KEYS = [\n 'user',\n 'teamManager',\n 'adminReview',\n 'adminOverride',\n 'system',\n] as const;\nexport type AuditActorMode = (typeof AUDIT_ACTOR_MODE_KEYS)[number];\n\nexport const AUDIT_ADMIN_ACTOR_MODE_KEYS = [\n 'adminReview',\n 'adminOverride',\n] as const satisfies readonly AuditActorMode[];\nexport type AuditAdminActorMode = (typeof AUDIT_ADMIN_ACTOR_MODE_KEYS)[number];\n\nexport const AUDIT_NON_ADMIN_ACTOR_MODE_KEYS = [\n 'user',\n 'teamManager',\n 'system',\n] as const satisfies readonly AuditActorMode[];\nexport type AuditNonAdminActorMode = (typeof AUDIT_NON_ADMIN_ACTOR_MODE_KEYS)[number];\n\nexport const AUDIT_SYSTEM_REASON_KEYS = ['trigger', 'scheduledJob', 'migration'] as const;\nexport type AuditSystemReason = (typeof AUDIT_SYSTEM_REASON_KEYS)[number];\n\nexport type CaptainTeamRole = (typeof CAPTAIN_TEAM_ROLES)[number];\n\n// `isAdmin` is metadata only: it records that the caller's token carried a global-role claim (admin\n// or referee) when they acted, and grants nothing. `systemRole` is required on the admin modes and\n// forbidden on the others, so an admin action is never recorded without the authority it used and a\n// non-admin action never carries one.\nexport type AuditActor =\n | { uid: string | null; isAdmin: boolean; actorMode: AuditNonAdminActorMode; systemRole?: never }\n | {\n uid: string | null;\n isAdmin: boolean;\n actorMode: AuditAdminActorMode;\n systemRole: SystemRole;\n };\n\nexport interface AuditTarget {\n // The user the action was performed on, when there is one.\n uid: string | null;\n // The slash path of the document the action changed, when there is one.\n ref: string | null;\n}\n\nexport const AUDIT_RESULT_KEYS = ['success', 'failure'] as const;\nexport type AuditResult = (typeof AUDIT_RESULT_KEYS)[number];\n"]}
|
package/dist/types/claims.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// `admin` and `referee` mirror the `_systemData/adminList` rosters; `userStatus` mirrors the
|
|
4
4
|
// profile's account status so rules and an open client can refuse a banned account that still
|
|
5
5
|
// holds a live token. A claim is a fast hint: a state-changing callable re-reads the roster
|
|
6
|
-
// (BACKEND-004). Team roles are never claims — they resolve from `teamMemberships` per request.
|
|
6
|
+
// (RULE-STD-BACKEND-004). Team roles are never claims — they resolve from `teamMemberships` per request.
|
|
7
7
|
export const SYSTEM_ROLE_CLAIM_KEYS = {
|
|
8
8
|
admin: 'admin',
|
|
9
9
|
referee: 'referee',
|
package/dist/types/claims.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claims.js","sourceRoot":"","sources":["../../src/types/claims.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,EAAE;AACF,6FAA6F;AAC7F,8FAA8F;AAC9F,4FAA4F;AAC5F,
|
|
1
|
+
{"version":3,"file":"claims.js","sourceRoot":"","sources":["../../src/types/claims.ts"],"names":[],"mappings":"AAAA,yFAAyF;AACzF,EAAE;AACF,6FAA6F;AAC7F,8FAA8F;AAC9F,4FAA4F;AAC5F,yGAAyG;AAIzG,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;CAC2B,CAAC;AAEhD,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAC;AASlD,MAAM,CAAC,MAAM,uBAAuB,GAAkB;IACpD,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,QAAQ;CACrB,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAA4B;IAC7D,OAAO;QACL,KAAK,EAAE,GAAG,CAAC,sBAAsB,CAAC,KAAK,CAAC,KAAK,IAAI;QACjD,OAAO,EAAE,GAAG,CAAC,sBAAsB,CAAC,OAAO,CAAC,KAAK,IAAI;QACrD,UAAU,EAAE,GAAG,CAAC,qBAAqB,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;KAC1E,CAAC;AACJ,CAAC","sourcesContent":["// The custom-claim contract — the one declaration both roots parse the ID token against.\n//\n// `admin` and `referee` mirror the `_systemData/adminList` rosters; `userStatus` mirrors the\n// profile's account status so rules and an open client can refuse a banned account that still\n// holds a live token. A claim is a fast hint: a state-changing callable re-reads the roster\n// (RULE-STD-BACKEND-004). Team roles are never claims — they resolve from `teamMemberships` per request.\n\nimport type { SystemRole, UserStatus } from './unions.js';\n\nexport const SYSTEM_ROLE_CLAIM_KEYS = {\n admin: 'admin',\n referee: 'referee',\n} as const satisfies Record<SystemRole, string>;\n\nexport const USER_STATUS_CLAIM_KEY = 'userStatus';\n\nexport interface QSportsClaims {\n admin: boolean;\n referee: boolean;\n // Absent on a token minted before any status was stamped; treated as `active` by the parser.\n userStatus: UserStatus;\n}\n\nexport const DEFAULT_Q_SPORTS_CLAIMS: QSportsClaims = {\n admin: false,\n referee: false,\n userStatus: 'active',\n};\n\n/**\n * Parse a raw ID-token claims object into the typed contract. A role is held only on an exact\n * `true`. An absent status claim reads as `active`: the claim only speeds up refusing a banned\n * account, and the server's profile check — which fails closed — is the authority.\n */\nexport function parseQSportsClaims(raw: Record<string, unknown>): QSportsClaims {\n return {\n admin: raw[SYSTEM_ROLE_CLAIM_KEYS.admin] === true,\n referee: raw[SYSTEM_ROLE_CLAIM_KEYS.referee] === true,\n userStatus: raw[USER_STATUS_CLAIM_KEY] === 'banned' ? 'banned' : 'active',\n };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Which document owns a picture (ARCH-102). An upload's target, its indexes, and a picture's
|
|
1
|
+
// Which document owns a picture (RULE-STD-ARCH-102). An upload's target, its indexes, and a picture's
|
|
2
2
|
// removal take the full union; a gallery picture document takes the gallery subset, because only
|
|
3
3
|
// those three owners hold a gallery — a location and an award hold one picture in a single slot.
|
|
4
4
|
export const PICTURE_OWNER_KIND_KEYS = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"picture-owners.js","sourceRoot":"","sources":["../../src/types/picture-owners.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"picture-owners.js","sourceRoot":"","sources":["../../src/types/picture-owners.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,iGAAiG;AACjG,iGAAiG;AAEjG,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,aAAa;IACb,YAAY;IACZ,aAAa;IACb,cAAc;IACd,iBAAiB;CACT,CAAC;AAGX,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,aAAa;IACb,YAAY;IACZ,aAAa;CACiC,CAAC;AAIjD,mEAAmE;AACnE,MAAM,CAAC,MAAM,2BAA2B,GAAG,iBAAqD,CAAC;AAEjG,6DAA6D;AAC7D,MAAM,CAAC,MAAM,8BAA8B,GAAG,YAAgD,CAAC;AAE/F,6EAA6E;AAC7E,MAAM,UAAU,kBAAkB,CAAC,IAAsB;IACvD,OAAQ,uBAAuD,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACjF,CAAC","sourcesContent":["// Which document owns a picture (RULE-STD-ARCH-102). An upload's target, its indexes, and a picture's\n// removal take the full union; a gallery picture document takes the gallery subset, because only\n// those three owners hold a gallery — a location and an award hold one picture in a single slot.\n\nexport const PICTURE_OWNER_KIND_KEYS = [\n 'sportLeague',\n 'leagueTeam',\n 'landingPage',\n 'gameLocation',\n 'awardDefinition',\n] as const;\nexport type PictureOwnerKind = (typeof PICTURE_OWNER_KIND_KEYS)[number];\n\nexport const GALLERY_OWNER_KIND_KEYS = [\n 'sportLeague',\n 'leagueTeam',\n 'landingPage',\n] as const satisfies readonly PictureOwnerKind[];\nexport type GalleryOwnerKind = (typeof GALLERY_OWNER_KIND_KEYS)[number];\nexport type PictureSlotOwnerKind = Exclude<PictureOwnerKind, GalleryOwnerKind>;\n\n// An award's badge slot, which the award catalog's own core fills.\nexport const AWARD_DEFINITION_OWNER_KIND = 'awardDefinition' as const satisfies PictureOwnerKind;\n\n// A team's gallery, which the team's deletion retires whole.\nexport const LEAGUE_TEAM_GALLERY_OWNER_KIND = 'leagueTeam' as const satisfies GalleryOwnerKind;\n\n/** Whether an owner holds a gallery, as opposed to a single picture slot. */\nexport function isGalleryOwnerKind(kind: PictureOwnerKind): kind is GalleryOwnerKind {\n return (GALLERY_OWNER_KIND_KEYS as readonly PictureOwnerKind[]).includes(kind);\n}\n"]}
|
package/dist/types/schedules.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Canonical unions of a league's schedule: its weeks and the games in them (ARCH-102).
|
|
1
|
+
// Canonical unions of a league's schedule: its weeks and the games in them (RULE-STD-ARCH-102).
|
|
2
2
|
// The two kinds of scheduling conflict the week form warns about, never blocks on: two games at one
|
|
3
3
|
// venue court at one start time, and one team booked into two games at one start time.
|
|
4
4
|
export const SCHEDULE_CONFLICT_KIND_KEYS = ['sharedLocation', 'teamDoubleBooked'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schedules.js","sourceRoot":"","sources":["../../src/types/schedules.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"schedules.js","sourceRoot":"","sources":["../../src/types/schedules.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAEhG,oGAAoG;AACpG,uFAAuF;AACvF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,gBAAgB,EAAE,kBAAkB,CAAU,CAAC;AAE3F,MAAM,CAAC,MAAM,wBAAwB,GAAG,gBAAwD,CAAC;AACjG,MAAM,CAAC,MAAM,2BAA2B,GACtC,kBAA0D,CAAC;AAE7D,kGAAkG;AAClG,qCAAqC;AACrC,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAU,CAAC;AAGhF,qGAAqG;AACrG,MAAM,CAAC,MAAM,8BAA8B,GAAG;IAC5C,QAAQ;IACR,OAAO;IACP,WAAW;IACX,gBAAgB;IAChB,aAAa;IACb,eAAe;CACP,CAAC;AAGX,8FAA8F;AAC9F,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,WAAW,EAAE,eAAe,EAAE,cAAc,CAAU,CAAC;AAGhG,oGAAoG;AACpG,sBAAsB;AACtB,MAAM,CAAC,MAAM,4BAA4B,GAAG;IAC1C,eAAe;IACf,UAAU;IACV,uBAAuB;IACvB,sBAAsB;IACtB,qBAAqB;CACb,CAAC","sourcesContent":["// Canonical unions of a league's schedule: its weeks and the games in them (RULE-STD-ARCH-102).\n\n// The two kinds of scheduling conflict the week form warns about, never blocks on: two games at one\n// venue court at one start time, and one team booked into two games at one start time.\nexport const SCHEDULE_CONFLICT_KIND_KEYS = ['sharedLocation', 'teamDoubleBooked'] as const;\nexport type ScheduleConflictKind = (typeof SCHEDULE_CONFLICT_KIND_KEYS)[number];\nexport const SHARED_LOCATION_CONFLICT = 'sharedLocation' as const satisfies ScheduleConflictKind;\nexport const TEAM_DOUBLE_BOOKED_CONFLICT =\n 'teamDoubleBooked' as const satisfies ScheduleConflictKind;\n\n// What a game's deletion was part of: the game alone, its whole week, or its team's deletion. The\n// deletion's audit event records it.\nexport const SPORT_GAME_DELETION_SCOPE_KEYS = ['game', 'week', 'team'] as const;\nexport type SportGameDeletionScope = (typeof SPORT_GAME_DELETION_SCOPE_KEYS)[number];\n\n// A game's schedule fields an admin edits, in the order the edit's result and audit event list them.\nexport const SPORT_GAME_SCHEDULE_FIELD_KEYS = [\n 'weekId',\n 'teams',\n 'startTime',\n 'gameLocationId',\n 'subLocation',\n 'locationLabel',\n] as const;\nexport type SportGameScheduleField = (typeof SPORT_GAME_SCHEDULE_FIELD_KEYS)[number];\n\n// The fields a week carries on every one of its games, which the week edit rewrites together.\nexport const SCHEDULE_WEEK_FIELD_KEYS = ['weekTitle', 'weekStartDate', 'weekLocation'] as const;\nexport type ScheduleWeekField = (typeof SCHEDULE_WEEK_FIELD_KEYS)[number];\n\n// Why the schedule callables refused, carried in the refusal's details so the admin screen can mark\n// the games it names.\nexport const SCHEDULE_REFUSAL_REASON_KEYS = [\n 'gameCompleted',\n 'gameHeld',\n 'weekHasCompletedGames',\n 'teamHasRecordedStats',\n 'gameHasRecordedPlay',\n] as const;\nexport type ScheduleRefusalReason = (typeof SCHEDULE_REFUSAL_REASON_KEYS)[number];\n"]}
|
package/dist/types/sports.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
// The canonical sport discriminator (
|
|
1
|
+
// The canonical sport discriminator (RULE-QS-SPORT-902), and each sport's declared vocabulary (RULE-QS-SPORT-907).
|
|
2
2
|
//
|
|
3
3
|
// `leagueType` identifies a sport everywhere. The lowercase sport key is the storage key derived
|
|
4
4
|
// from it — the `sportHallOfFame/{sportKey}` and `historicalStats/{sportKey}` document ids and the
|
|
5
5
|
// `lifetimeStats.{sportKey}` field. Both directions of the mapping live here, never in an inline
|
|
6
|
-
// conditional. What each sport DOES belongs to its sport adapter (SPORT-
|
|
6
|
+
// conditional. What each sport DOES belongs to its sport adapter (RULE-QS-SPORT-903), not to this file.
|
|
7
7
|
export const LEAGUE_TYPE_KEYS = ['Basketball', 'Curling', 'Football'];
|
|
8
8
|
export const SPORT_KEYS = ['basketball', 'curling', 'football'];
|
|
9
9
|
export const SPORT_KEY_BY_LEAGUE_TYPE = {
|
package/dist/types/sports.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sports.js","sourceRoot":"","sources":["../../src/types/sports.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"sports.js","sourceRoot":"","sources":["../../src/types/sports.ts"],"names":[],"mappings":"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","sourcesContent":["// The canonical sport discriminator (RULE-QS-SPORT-902), and each sport's declared vocabulary (RULE-QS-SPORT-907).\n//\n// `leagueType` identifies a sport everywhere. The lowercase sport key is the storage key derived\n// from it — the `sportHallOfFame/{sportKey}` and `historicalStats/{sportKey}` document ids and the\n// `lifetimeStats.{sportKey}` field. Both directions of the mapping live here, never in an inline\n// conditional. What each sport DOES belongs to its sport adapter (RULE-QS-SPORT-903), not to this file.\n\nexport const LEAGUE_TYPE_KEYS = ['Basketball', 'Curling', 'Football'] as const;\nexport type LeagueType = (typeof LEAGUE_TYPE_KEYS)[number];\n\nexport const SPORT_KEYS = ['basketball', 'curling', 'football'] as const;\nexport type SportKey = (typeof SPORT_KEYS)[number];\n\nexport const SPORT_KEY_BY_LEAGUE_TYPE = {\n Basketball: 'basketball',\n Curling: 'curling',\n Football: 'football',\n} as const satisfies Record<LeagueType, SportKey>;\n\nexport const LEAGUE_TYPE_BY_SPORT_KEY = {\n basketball: 'Basketball',\n curling: 'Curling',\n football: 'Football',\n} as const satisfies Record<SportKey, LeagueType>;\n\n// The glyph a sport renders, named by its adapter's `display.iconKey`. The app's one sport-icon\n// component maps each key to a glyph, so no surface picks an icon by sport.\nexport const SPORT_ICON_KEYS = ['basketballBall', 'curlingStone', 'footballBall'] as const;\nexport type SportIconKey = (typeof SPORT_ICON_KEYS)[number];\n\n// Every counter a stat line holds, across every sport. Each sport's team and player counters are a\n// subset; a derived field (basketball's `fantasyPoints`) is not a counter.\nexport const STAT_COUNTER_KEYS = ['score', 'timeouts', 'points', 'rebounds', 'assists'] as const;\nexport type StatCounterKey = (typeof STAT_COUNTER_KEYS)[number];\n\n// ---------------------------------------------------------------------------------------------\n// Basketball — player-scored: a team's score is the sum of its players' points.\n// ---------------------------------------------------------------------------------------------\n\nexport const BASKETBALL_TEAM_STAT_KEYS = [\n 'score',\n 'timeouts',\n] as const satisfies readonly StatCounterKey[];\nexport type BasketballTeamStatKey = (typeof BASKETBALL_TEAM_STAT_KEYS)[number];\n\nexport const BASKETBALL_PLAYER_STAT_KEYS = [\n 'points',\n 'rebounds',\n 'assists',\n] as const satisfies readonly StatCounterKey[];\nexport type BasketballPlayerStatKey = (typeof BASKETBALL_PLAYER_STAT_KEYS)[number];\n\n// A bulk edit names the player counter it moves.\nexport const BASKETBALL_BULK_STAT_KEYS = BASKETBALL_PLAYER_STAT_KEYS;\nexport type BasketballBulkStatKey = BasketballPlayerStatKey;\n\nexport const BASKETBALL_ONE_POINT_EVENT_TYPE = '1PT';\nexport const BASKETBALL_TWO_POINT_EVENT_TYPE = '2PT';\nexport const BASKETBALL_THREE_POINT_EVENT_TYPE = '3PT';\n// Only a two- or three-point shot may name the teammate who assisted it.\nexport const BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS = [\n BASKETBALL_TWO_POINT_EVENT_TYPE,\n BASKETBALL_THREE_POINT_EVENT_TYPE,\n] as const;\nexport const BASKETBALL_SCORE_EVENT_TYPE_KEYS = [\n BASKETBALL_ONE_POINT_EVENT_TYPE,\n ...BASKETBALL_ASSISTABLE_SHOT_EVENT_TYPE_KEYS,\n] as const;\nexport const BASKETBALL_REBOUND_EVENT_TYPE = 'REBOUND';\nexport const BASKETBALL_ASSIST_EVENT_TYPE = 'ASSIST';\nexport const BASKETBALL_PLAYER_TALLY_EVENT_TYPE_KEYS = [\n BASKETBALL_REBOUND_EVENT_TYPE,\n BASKETBALL_ASSIST_EVENT_TYPE,\n] as const;\n// A timeout is the team's; it names no player.\nexport const BASKETBALL_TIMEOUT_EVENT_TYPE = 'TIMEOUT';\nexport const BASKETBALL_BULK_EDIT_EVENT_TYPE = 'BULK_EDIT';\n\nexport const BASKETBALL_STAT_EVENT_TYPE_KEYS = [\n ...BASKETBALL_SCORE_EVENT_TYPE_KEYS,\n ...BASKETBALL_PLAYER_TALLY_EVENT_TYPE_KEYS,\n BASKETBALL_TIMEOUT_EVENT_TYPE,\n BASKETBALL_BULK_EDIT_EVENT_TYPE,\n] as const;\nexport type BasketballStatEventType = (typeof BASKETBALL_STAT_EVENT_TYPE_KEYS)[number];\n\n// ---------------------------------------------------------------------------------------------\n// Curling — team-scored by end; no player lines.\n// ---------------------------------------------------------------------------------------------\n\nexport const CURLING_TEAM_STAT_KEYS = ['score'] as const satisfies readonly StatCounterKey[];\nexport type CurlingTeamStatKey = (typeof CURLING_TEAM_STAT_KEYS)[number];\nexport const CURLING_PLAYER_STAT_KEYS = [] as const satisfies readonly StatCounterKey[];\n\nexport const CURLING_ROUND_SCORE_EVENT_TYPE = 'CURLING_ROUND_SCORE';\n// An end nobody scored; it names no team.\nexport const CURLING_ROUND_BLANK_EVENT_TYPE = 'CURLING_ROUND_BLANK';\nexport const CURLING_STAT_EVENT_TYPE_KEYS = [\n CURLING_ROUND_SCORE_EVENT_TYPE,\n CURLING_ROUND_BLANK_EVENT_TYPE,\n] as const;\nexport type CurlingStatEventType = (typeof CURLING_STAT_EVENT_TYPE_KEYS)[number];\n\n// ---------------------------------------------------------------------------------------------\n// Football — team-scored; no player lines.\n// ---------------------------------------------------------------------------------------------\n\nexport const FOOTBALL_TEAM_STAT_KEYS = ['score'] as const satisfies readonly StatCounterKey[];\nexport type FootballTeamStatKey = (typeof FOOTBALL_TEAM_STAT_KEYS)[number];\nexport const FOOTBALL_PLAYER_STAT_KEYS = [] as const satisfies readonly StatCounterKey[];\n\n// Named by the points each adds: a +2 is a safety or a conversion, and the game records only points.\nexport const FOOTBALL_SIX_POINT_EVENT_TYPE = 'FOOTBALL_6PT';\nexport const FOOTBALL_TWO_POINT_EVENT_TYPE = 'FOOTBALL_2PT';\nexport const FOOTBALL_ONE_POINT_EVENT_TYPE = 'FOOTBALL_1PT';\nexport const FOOTBALL_SCORE_EVENT_TYPE_KEYS = [\n FOOTBALL_SIX_POINT_EVENT_TYPE,\n FOOTBALL_TWO_POINT_EVENT_TYPE,\n FOOTBALL_ONE_POINT_EVENT_TYPE,\n] as const;\nexport const FOOTBALL_BULK_EDIT_EVENT_TYPE = 'FOOTBALL_BULK_EDIT';\nexport const FOOTBALL_STAT_EVENT_TYPE_KEYS = [\n ...FOOTBALL_SCORE_EVENT_TYPE_KEYS,\n FOOTBALL_BULK_EDIT_EVENT_TYPE,\n] as const;\nexport type FootballStatEventType = (typeof FOOTBALL_STAT_EVENT_TYPE_KEYS)[number];\n"]}
|
package/dist/types/stats.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Canonical unions of the stat event store and the stats operations (ARCH-102). What each sport's
|
|
1
|
+
// Canonical unions of the stat event store and the stats operations (RULE-STD-ARCH-102). What each sport's
|
|
2
2
|
// own events and lines are is ./sports.ts; these are the sport-agnostic halves every sport shares.
|
|
3
3
|
import { CAPTAIN_TEAM_ROLES, SYSTEM_ROLE_KEYS } from './unions.js';
|
|
4
4
|
// The two store-level events, members of every sport's event union. A void undoes the one event it
|
|
@@ -10,7 +10,7 @@ export const STAT_STORE_EVENT_TYPE_KEYS = [
|
|
|
10
10
|
STAT_CORRECTION_EVENT_TYPE,
|
|
11
11
|
];
|
|
12
12
|
// The fields of a stored stat event the writing core derives — its place in the replay, and who
|
|
13
|
-
// recorded it under which authority — so a caller never sends them (ARCH-106).
|
|
13
|
+
// recorded it under which authority — so a caller never sends them (RULE-STD-ARCH-106).
|
|
14
14
|
export const STAT_EVENT_RECORDER_FIELD_KEYS = [
|
|
15
15
|
'sequence',
|
|
16
16
|
'acceptedAt',
|
|
@@ -18,7 +18,7 @@ export const STAT_EVENT_RECORDER_FIELD_KEYS = [
|
|
|
18
18
|
'recordedByAuthority',
|
|
19
19
|
'recordedByTeamId',
|
|
20
20
|
];
|
|
21
|
-
// The name snapshots only a copied event carries; nothing writes one on a new event (SPORT-
|
|
21
|
+
// The name snapshots only a copied event carries; nothing writes one on a new event (RULE-QS-SPORT-914).
|
|
22
22
|
export const STAT_EVENT_SNAPSHOT_FIELD_KEYS = [
|
|
23
23
|
'displayNameSnapshot',
|
|
24
24
|
'assistedByDisplayNameSnapshot',
|
|
@@ -97,7 +97,7 @@ export const BULK_ENTRY_KIND_KEYS = ['playerLines', 'teamScores', 'rounds'];
|
|
|
97
97
|
// by an earlier send and acknowledged it without applying it again.
|
|
98
98
|
export const RECORDED_STAT_EVENT_OUTCOME_KEYS = ['recorded', 'alreadyRecorded'];
|
|
99
99
|
// What finalize did: made the game's numbers permanent, or found it already finalized and changed
|
|
100
|
-
// nothing (SPORT-
|
|
100
|
+
// nothing (RULE-QS-SPORT-923).
|
|
101
101
|
export const GAME_FINALIZE_OUTCOME_KEYS = ['finalized', 'alreadyFinalized'];
|
|
102
102
|
// What reopen did: took a finalized game's numbers back out, or found the game already open and
|
|
103
103
|
// changed nothing.
|
|
@@ -105,7 +105,7 @@ export const GAME_REOPEN_OUTCOME_KEYS = ['reopened', 'alreadyOpen'];
|
|
|
105
105
|
// Why a path that makes numbers permanent, or takes them back, refused a game whose stored numbers
|
|
106
106
|
// disagree with what produced them — something changed them outside the app, and an admin
|
|
107
107
|
// reconciles the game in Fix stats first. Finalize, reopen, and a ghost link never adopt or discard
|
|
108
|
-
// an unexplained difference (ENG-009):
|
|
108
|
+
// an unexplained difference (RULE-STD-ENG-009):
|
|
109
109
|
// statsOutOfBand the rollup or score mirror is not the replay of the game's events or record
|
|
110
110
|
// finalRecordMissing a completed game has no finalized record
|
|
111
111
|
// aggregateBelowZero a stored derived line holds less than the game put into it
|
package/dist/types/stats.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/types/stats.ts"],"names":[],"mappings":"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","sourcesContent":["// Canonical unions of the stat event store and the stats operations (ARCH-102). What each sport's\n// own events and lines are is ./sports.ts; these are the sport-agnostic halves every sport shares.\n\nimport { CAPTAIN_TEAM_ROLES, SYSTEM_ROLE_KEYS } from './unions.js';\n\n// The two store-level events, members of every sport's event union. A void undoes the one event it\n// targets; a correction adds a signed value to one correctable field of one line.\nexport const STAT_VOID_EVENT_TYPE = 'STAT_VOID';\nexport const STAT_CORRECTION_EVENT_TYPE = 'STAT_CORRECTION';\nexport const STAT_STORE_EVENT_TYPE_KEYS = [\n STAT_VOID_EVENT_TYPE,\n STAT_CORRECTION_EVENT_TYPE,\n] as const;\nexport type StatStoreEventType = (typeof STAT_STORE_EVENT_TYPE_KEYS)[number];\n\n// The fields of a stored stat event the writing core derives — its place in the replay, and who\n// recorded it under which authority — so a caller never sends them (ARCH-106).\nexport const STAT_EVENT_RECORDER_FIELD_KEYS = [\n 'sequence',\n 'acceptedAt',\n 'recordedByUserId',\n 'recordedByAuthority',\n 'recordedByTeamId',\n] as const;\nexport type StatEventRecorderField = (typeof STAT_EVENT_RECORDER_FIELD_KEYS)[number];\n\n// The name snapshots only a copied event carries; nothing writes one on a new event (SPORT-104).\nexport const STAT_EVENT_SNAPSHOT_FIELD_KEYS = [\n 'displayNameSnapshot',\n 'assistedByDisplayNameSnapshot',\n] as const;\nexport type StatEventSnapshotField = (typeof STAT_EVENT_SNAPSHOT_FIELD_KEYS)[number];\n\n// Who appended a correction: an admin reconciling a game, or the copy that carries a recorded\n// result its events do not explain.\nexport const STAT_CORRECTION_SOURCE_KEYS = ['admin', 'migration'] as const;\nexport type StatCorrectionSource = (typeof STAT_CORRECTION_SOURCE_KEYS)[number];\n\n// The authority the writing core confirmed for an event: a global role, or a team role on one of\n// the game's teams.\nexport const STAT_EVENT_AUTHORITY_KEYS = [...SYSTEM_ROLE_KEYS, ...CAPTAIN_TEAM_ROLES] as const;\nexport type StatEventAuthority = (typeof STAT_EVENT_AUTHORITY_KEYS)[number];\n\n// Every kind of stat line: the four player kinds, then the two team kinds. A sport's line of each\n// kind is declared once, in `SPORT_LINE_SCHEMAS`; a kind a sport has no line for is `never` there.\nexport const PLAYER_STAT_LINE_KIND_KEYS = [\n 'gamePlayer',\n 'membershipRow',\n 'lifetime',\n 'hallOfFame',\n] as const;\nexport const TEAM_STAT_LINE_KIND_KEYS = ['gameTeam', 'teamSeason'] as const;\nexport const STAT_LINE_KIND_KEYS = [\n ...PLAYER_STAT_LINE_KIND_KEYS,\n ...TEAM_STAT_LINE_KIND_KEYS,\n] as const;\nexport type StatLineKind = (typeof STAT_LINE_KIND_KEYS)[number];\nexport type PlayerStatLineKind = (typeof PLAYER_STAT_LINE_KIND_KEYS)[number];\n\n// One logical run of a stats action, recorded on its `statsOperations` document.\nexport const STATS_OPERATION_KIND_KEYS = [\n 'leagueStatsRebuild',\n 'lifetimeStatsRebuild',\n 'hallOfFameRebuild',\n 'statsValidation',\n 'gameStatsCorrection',\n 'gameStatsRecalculation',\n 'historicalStatsUpdate',\n 'ghostPlayerStats',\n 'gameDeletion',\n] as const;\nexport type StatsOperationKind = (typeof STATS_OPERATION_KIND_KEYS)[number];\n\n// The rebuilds: each replaces one destination from the finalized games, a unit at a time, and shares\n// one paged run.\nexport const STATS_REBUILD_OPERATION_KIND_KEYS = [\n 'leagueStatsRebuild',\n 'lifetimeStatsRebuild',\n 'hallOfFameRebuild',\n] as const satisfies readonly StatsOperationKind[];\nexport type StatsRebuildOperationKind = (typeof STATS_REBUILD_OPERATION_KIND_KEYS)[number];\n\nexport const STATS_OPERATION_STATUS_KEYS = ['running', 'complete', 'stopped'] as const;\nexport type StatsOperationStatus = (typeof STATS_OPERATION_STATUS_KEYS)[number];\n\n// A validation run checks every game first, then the destinations those games feed.\nexport const STATS_VALIDATION_PHASE_KEYS = ['games', 'destinations'] as const;\nexport type StatsValidationPhase = (typeof STATS_VALIDATION_PHASE_KEYS)[number];\n\n// A ghost has one operation for both of its ways out, so a link and a removal refuse each other.\nexport const GHOST_STATS_OPERATION_ACTION_KEYS = ['link', 'removal'] as const;\nexport type GhostStatsOperationAction = (typeof GHOST_STATS_OPERATION_ACTION_KEYS)[number];\n\n// Why a scoring write refused an event. The first ten are a sport adapter's `validate`; the last\n// four are the store driver's own: an id already stored, or earlier in the batch, with different\n// content; a void whose target is missing, a void, or a correction; a correction sent to a scoring\n// entry, which only the game-reconcile core appends; and a void that would leave a stat below zero,\n// because a later edit already moved its target's field down.\nexport const STAT_EVENT_REFUSAL_KEYS = [\n 'eventTypeNotInSport',\n 'teamNotInGame',\n 'playerNotRostered',\n 'assisterNotRostered',\n 'assistNotAllowed',\n 'playerNotAllowed',\n 'roundNotNext',\n 'roundsComplete',\n 'bulkValueInvalid',\n 'bulkStale',\n 'eventIdConflict',\n 'voidTargetNotSportEvent',\n 'correctionNotAccepted',\n 'undoBelowZero',\n] as const;\nexport type StatEventRefusalCode = (typeof STAT_EVENT_REFUSAL_KEYS)[number];\n\n// Why a game may not be finalized yet — a sport played in rounds with an end still unrecorded.\nexport const FINALIZATION_NOT_READY_KEYS = ['roundsIncomplete'] as const;\nexport type FinalizationNotReadyReason = (typeof FINALIZATION_NOT_READY_KEYS)[number];\n\n// The scoring panel a sport's adapter names; the scoring screen renders one component per kind.\nexport const SCORING_PANEL_KIND_KEYS = ['playerEvents', 'teamPoints', 'rounds'] as const;\nexport type ScoringPanelKind = (typeof SCORING_PANEL_KIND_KEYS)[number];\n\n// The bulk-entry form body a sport's adapter names; the bulk-entry dialog renders one per kind.\nexport const BULK_ENTRY_KIND_KEYS = ['playerLines', 'teamScores', 'rounds'] as const;\nexport type BulkEntryKind = (typeof BULK_ENTRY_KIND_KEYS)[number];\n\n// What a scoring write did with each event it was sent: stored it now, or found it already stored\n// by an earlier send and acknowledged it without applying it again.\nexport const RECORDED_STAT_EVENT_OUTCOME_KEYS = ['recorded', 'alreadyRecorded'] as const;\nexport type RecordedStatEventOutcome = (typeof RECORDED_STAT_EVENT_OUTCOME_KEYS)[number];\n\n// What finalize did: made the game's numbers permanent, or found it already finalized and changed\n// nothing (SPORT-203).\nexport const GAME_FINALIZE_OUTCOME_KEYS = ['finalized', 'alreadyFinalized'] as const;\nexport type GameFinalizeOutcome = (typeof GAME_FINALIZE_OUTCOME_KEYS)[number];\n\n// What reopen did: took a finalized game's numbers back out, or found the game already open and\n// changed nothing.\nexport const GAME_REOPEN_OUTCOME_KEYS = ['reopened', 'alreadyOpen'] as const;\nexport type GameReopenOutcome = (typeof GAME_REOPEN_OUTCOME_KEYS)[number];\n\n// Why a path that makes numbers permanent, or takes them back, refused a game whose stored numbers\n// disagree with what produced them — something changed them outside the app, and an admin\n// reconciles the game in Fix stats first. Finalize, reopen, and a ghost link never adopt or discard\n// an unexplained difference (ENG-009):\n// statsOutOfBand the rollup or score mirror is not the replay of the game's events or record\n// finalRecordMissing a completed game has no finalized record\n// aggregateBelowZero a stored derived line holds less than the game put into it\nexport const STATS_INTEGRITY_REFUSAL_KEYS = [\n 'statsOutOfBand',\n 'finalRecordMissing',\n 'aggregateBelowZero',\n] as const;\nexport type StatsIntegrityRefusal = (typeof STATS_INTEGRITY_REFUSAL_KEYS)[number];\n\n// What a game repair in Fix stats did: changed the game (`reconciled`), found nothing to change\n// (`unchanged`), or found its operation already committed and acknowledged the retry\n// (`alreadyApplied`).\nexport const GAME_STATS_REPAIR_OUTCOME_KEYS = [\n 'reconciled',\n 'unchanged',\n 'alreadyApplied',\n] as const;\nexport type GameStatsRepairOutcome = (typeof GAME_STATS_REPAIR_OUTCOME_KEYS)[number];\n\n// Why a game repair in Fix stats was refused, in the refusal's details, so the form says what to do:\n// eventUnreadable an event document no longer parses or replays — fix it in the console first\n// eventSequenceGap the events do not hold exactly the sequences 1..n — a gap or a repeat — which\n// a repair never renumbers: fix the event documents in the console first\n// sourcesDisagree the record, the stored rollup, and the events all disagree: no one of them\n// says what finalize applied\n// scoreAmbiguous keep-stored: the team line's score and the score mirror were both edited, to\n// different values — give the score as a target instead\n// fieldNotCorrectable a field the sport's adapter does not let a correction change — restore from\n// the events instead, or reopen and re-score\n// lineNotRostered a line for someone not on the game's roster\n// teamNotInGame a target names a team the game does not hold\n// gameTooLarge the repair would not fit in one commit\nexport const GAME_REPAIR_REFUSAL_KEYS = [\n 'eventUnreadable',\n 'eventSequenceGap',\n 'sourcesDisagree',\n 'scoreAmbiguous',\n 'fieldNotCorrectable',\n 'lineNotRostered',\n 'teamNotInGame',\n 'gameTooLarge',\n] as const;\nexport type GameRepairRefusal = (typeof GAME_REPAIR_REFUSAL_KEYS)[number];\n\n// What a ghost link did with the team's memberships: the ghost's membership became the account's\n// (`handedOver`); the account had none and the ghost none either, so the closed-league link gave the\n// account one (`created`); both held one and one survives with the higher role (`merged`); or only\n// the account held one, and it stands (`kept`).\nexport const GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS = [\n 'handedOver',\n 'created',\n 'merged',\n 'kept',\n] as const;\nexport type GhostLinkMembershipOutcome = (typeof GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS)[number];\n\n// What the migration's placement of an unplaceable V1 stat line did: `alreadyResolved` when the game\n// already held the entry it would write — nothing was written.\nexport const UNROSTERED_STAT_LINE_RESOLUTION_OUTCOME_KEYS = [\n 'resolved',\n 'alreadyResolved',\n] as const;\nexport type UnrosteredStatLineResolutionOutcome =\n (typeof UNROSTERED_STAT_LINE_RESOLUTION_OUTCOME_KEYS)[number];\n\n// Why a ghost's removal was refused, in the refusal's details, so the client answers each one: the\n// ghost has played (link it instead) or its removal stopped on finding it had; a game the removal\n// needs is held by another operation (try again shortly); the ghost is being, or was, linked; the\n// ghost is the team's captain (change the captain first).\nexport const GHOST_REMOVAL_REFUSAL_KEYS = [\n 'ghostHasPlayed',\n 'removalStopped',\n 'gameHeld',\n 'ghostBeingLinked',\n 'captainNotRemovable',\n] as const;\nexport type GhostRemovalRefusal = (typeof GHOST_REMOVAL_REFUSAL_KEYS)[number];\n"]}
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/types/stats.ts"],"names":[],"mappings":"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","sourcesContent":["// Canonical unions of the stat event store and the stats operations (RULE-STD-ARCH-102). What each sport's\n// own events and lines are is ./sports.ts; these are the sport-agnostic halves every sport shares.\n\nimport { CAPTAIN_TEAM_ROLES, SYSTEM_ROLE_KEYS } from './unions.js';\n\n// The two store-level events, members of every sport's event union. A void undoes the one event it\n// targets; a correction adds a signed value to one correctable field of one line.\nexport const STAT_VOID_EVENT_TYPE = 'STAT_VOID';\nexport const STAT_CORRECTION_EVENT_TYPE = 'STAT_CORRECTION';\nexport const STAT_STORE_EVENT_TYPE_KEYS = [\n STAT_VOID_EVENT_TYPE,\n STAT_CORRECTION_EVENT_TYPE,\n] as const;\nexport type StatStoreEventType = (typeof STAT_STORE_EVENT_TYPE_KEYS)[number];\n\n// The fields of a stored stat event the writing core derives — its place in the replay, and who\n// recorded it under which authority — so a caller never sends them (RULE-STD-ARCH-106).\nexport const STAT_EVENT_RECORDER_FIELD_KEYS = [\n 'sequence',\n 'acceptedAt',\n 'recordedByUserId',\n 'recordedByAuthority',\n 'recordedByTeamId',\n] as const;\nexport type StatEventRecorderField = (typeof STAT_EVENT_RECORDER_FIELD_KEYS)[number];\n\n// The name snapshots only a copied event carries; nothing writes one on a new event (RULE-QS-SPORT-914).\nexport const STAT_EVENT_SNAPSHOT_FIELD_KEYS = [\n 'displayNameSnapshot',\n 'assistedByDisplayNameSnapshot',\n] as const;\nexport type StatEventSnapshotField = (typeof STAT_EVENT_SNAPSHOT_FIELD_KEYS)[number];\n\n// Who appended a correction: an admin reconciling a game, or the copy that carries a recorded\n// result its events do not explain.\nexport const STAT_CORRECTION_SOURCE_KEYS = ['admin', 'migration'] as const;\nexport type StatCorrectionSource = (typeof STAT_CORRECTION_SOURCE_KEYS)[number];\n\n// The authority the writing core confirmed for an event: a global role, or a team role on one of\n// the game's teams.\nexport const STAT_EVENT_AUTHORITY_KEYS = [...SYSTEM_ROLE_KEYS, ...CAPTAIN_TEAM_ROLES] as const;\nexport type StatEventAuthority = (typeof STAT_EVENT_AUTHORITY_KEYS)[number];\n\n// Every kind of stat line: the four player kinds, then the two team kinds. A sport's line of each\n// kind is declared once, in `SPORT_LINE_SCHEMAS`; a kind a sport has no line for is `never` there.\nexport const PLAYER_STAT_LINE_KIND_KEYS = [\n 'gamePlayer',\n 'membershipRow',\n 'lifetime',\n 'hallOfFame',\n] as const;\nexport const TEAM_STAT_LINE_KIND_KEYS = ['gameTeam', 'teamSeason'] as const;\nexport const STAT_LINE_KIND_KEYS = [\n ...PLAYER_STAT_LINE_KIND_KEYS,\n ...TEAM_STAT_LINE_KIND_KEYS,\n] as const;\nexport type StatLineKind = (typeof STAT_LINE_KIND_KEYS)[number];\nexport type PlayerStatLineKind = (typeof PLAYER_STAT_LINE_KIND_KEYS)[number];\n\n// One logical run of a stats action, recorded on its `statsOperations` document.\nexport const STATS_OPERATION_KIND_KEYS = [\n 'leagueStatsRebuild',\n 'lifetimeStatsRebuild',\n 'hallOfFameRebuild',\n 'statsValidation',\n 'gameStatsCorrection',\n 'gameStatsRecalculation',\n 'historicalStatsUpdate',\n 'ghostPlayerStats',\n 'gameDeletion',\n] as const;\nexport type StatsOperationKind = (typeof STATS_OPERATION_KIND_KEYS)[number];\n\n// The rebuilds: each replaces one destination from the finalized games, a unit at a time, and shares\n// one paged run.\nexport const STATS_REBUILD_OPERATION_KIND_KEYS = [\n 'leagueStatsRebuild',\n 'lifetimeStatsRebuild',\n 'hallOfFameRebuild',\n] as const satisfies readonly StatsOperationKind[];\nexport type StatsRebuildOperationKind = (typeof STATS_REBUILD_OPERATION_KIND_KEYS)[number];\n\nexport const STATS_OPERATION_STATUS_KEYS = ['running', 'complete', 'stopped'] as const;\nexport type StatsOperationStatus = (typeof STATS_OPERATION_STATUS_KEYS)[number];\n\n// A validation run checks every game first, then the destinations those games feed.\nexport const STATS_VALIDATION_PHASE_KEYS = ['games', 'destinations'] as const;\nexport type StatsValidationPhase = (typeof STATS_VALIDATION_PHASE_KEYS)[number];\n\n// A ghost has one operation for both of its ways out, so a link and a removal refuse each other.\nexport const GHOST_STATS_OPERATION_ACTION_KEYS = ['link', 'removal'] as const;\nexport type GhostStatsOperationAction = (typeof GHOST_STATS_OPERATION_ACTION_KEYS)[number];\n\n// Why a scoring write refused an event. The first ten are a sport adapter's `validate`; the last\n// four are the store driver's own: an id already stored, or earlier in the batch, with different\n// content; a void whose target is missing, a void, or a correction; a correction sent to a scoring\n// entry, which only the game-reconcile core appends; and a void that would leave a stat below zero,\n// because a later edit already moved its target's field down.\nexport const STAT_EVENT_REFUSAL_KEYS = [\n 'eventTypeNotInSport',\n 'teamNotInGame',\n 'playerNotRostered',\n 'assisterNotRostered',\n 'assistNotAllowed',\n 'playerNotAllowed',\n 'roundNotNext',\n 'roundsComplete',\n 'bulkValueInvalid',\n 'bulkStale',\n 'eventIdConflict',\n 'voidTargetNotSportEvent',\n 'correctionNotAccepted',\n 'undoBelowZero',\n] as const;\nexport type StatEventRefusalCode = (typeof STAT_EVENT_REFUSAL_KEYS)[number];\n\n// Why a game may not be finalized yet — a sport played in rounds with an end still unrecorded.\nexport const FINALIZATION_NOT_READY_KEYS = ['roundsIncomplete'] as const;\nexport type FinalizationNotReadyReason = (typeof FINALIZATION_NOT_READY_KEYS)[number];\n\n// The scoring panel a sport's adapter names; the scoring screen renders one component per kind.\nexport const SCORING_PANEL_KIND_KEYS = ['playerEvents', 'teamPoints', 'rounds'] as const;\nexport type ScoringPanelKind = (typeof SCORING_PANEL_KIND_KEYS)[number];\n\n// The bulk-entry form body a sport's adapter names; the bulk-entry dialog renders one per kind.\nexport const BULK_ENTRY_KIND_KEYS = ['playerLines', 'teamScores', 'rounds'] as const;\nexport type BulkEntryKind = (typeof BULK_ENTRY_KIND_KEYS)[number];\n\n// What a scoring write did with each event it was sent: stored it now, or found it already stored\n// by an earlier send and acknowledged it without applying it again.\nexport const RECORDED_STAT_EVENT_OUTCOME_KEYS = ['recorded', 'alreadyRecorded'] as const;\nexport type RecordedStatEventOutcome = (typeof RECORDED_STAT_EVENT_OUTCOME_KEYS)[number];\n\n// What finalize did: made the game's numbers permanent, or found it already finalized and changed\n// nothing (RULE-QS-SPORT-923).\nexport const GAME_FINALIZE_OUTCOME_KEYS = ['finalized', 'alreadyFinalized'] as const;\nexport type GameFinalizeOutcome = (typeof GAME_FINALIZE_OUTCOME_KEYS)[number];\n\n// What reopen did: took a finalized game's numbers back out, or found the game already open and\n// changed nothing.\nexport const GAME_REOPEN_OUTCOME_KEYS = ['reopened', 'alreadyOpen'] as const;\nexport type GameReopenOutcome = (typeof GAME_REOPEN_OUTCOME_KEYS)[number];\n\n// Why a path that makes numbers permanent, or takes them back, refused a game whose stored numbers\n// disagree with what produced them — something changed them outside the app, and an admin\n// reconciles the game in Fix stats first. Finalize, reopen, and a ghost link never adopt or discard\n// an unexplained difference (RULE-STD-ENG-009):\n// statsOutOfBand the rollup or score mirror is not the replay of the game's events or record\n// finalRecordMissing a completed game has no finalized record\n// aggregateBelowZero a stored derived line holds less than the game put into it\nexport const STATS_INTEGRITY_REFUSAL_KEYS = [\n 'statsOutOfBand',\n 'finalRecordMissing',\n 'aggregateBelowZero',\n] as const;\nexport type StatsIntegrityRefusal = (typeof STATS_INTEGRITY_REFUSAL_KEYS)[number];\n\n// What a game repair in Fix stats did: changed the game (`reconciled`), found nothing to change\n// (`unchanged`), or found its operation already committed and acknowledged the retry\n// (`alreadyApplied`).\nexport const GAME_STATS_REPAIR_OUTCOME_KEYS = [\n 'reconciled',\n 'unchanged',\n 'alreadyApplied',\n] as const;\nexport type GameStatsRepairOutcome = (typeof GAME_STATS_REPAIR_OUTCOME_KEYS)[number];\n\n// Why a game repair in Fix stats was refused, in the refusal's details, so the form says what to do:\n// eventUnreadable an event document no longer parses or replays — fix it in the console first\n// eventSequenceGap the events do not hold exactly the sequences 1..n — a gap or a repeat — which\n// a repair never renumbers: fix the event documents in the console first\n// sourcesDisagree the record, the stored rollup, and the events all disagree: no one of them\n// says what finalize applied\n// scoreAmbiguous keep-stored: the team line's score and the score mirror were both edited, to\n// different values — give the score as a target instead\n// fieldNotCorrectable a field the sport's adapter does not let a correction change — restore from\n// the events instead, or reopen and re-score\n// lineNotRostered a line for someone not on the game's roster\n// teamNotInGame a target names a team the game does not hold\n// gameTooLarge the repair would not fit in one commit\nexport const GAME_REPAIR_REFUSAL_KEYS = [\n 'eventUnreadable',\n 'eventSequenceGap',\n 'sourcesDisagree',\n 'scoreAmbiguous',\n 'fieldNotCorrectable',\n 'lineNotRostered',\n 'teamNotInGame',\n 'gameTooLarge',\n] as const;\nexport type GameRepairRefusal = (typeof GAME_REPAIR_REFUSAL_KEYS)[number];\n\n// What a ghost link did with the team's memberships: the ghost's membership became the account's\n// (`handedOver`); the account had none and the ghost none either, so the closed-league link gave the\n// account one (`created`); both held one and one survives with the higher role (`merged`); or only\n// the account held one, and it stands (`kept`).\nexport const GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS = [\n 'handedOver',\n 'created',\n 'merged',\n 'kept',\n] as const;\nexport type GhostLinkMembershipOutcome = (typeof GHOST_LINK_MEMBERSHIP_OUTCOME_KEYS)[number];\n\n// What the migration's placement of an unplaceable V1 stat line did: `alreadyResolved` when the game\n// already held the entry it would write — nothing was written.\nexport const UNROSTERED_STAT_LINE_RESOLUTION_OUTCOME_KEYS = [\n 'resolved',\n 'alreadyResolved',\n] as const;\nexport type UnrosteredStatLineResolutionOutcome =\n (typeof UNROSTERED_STAT_LINE_RESOLUTION_OUTCOME_KEYS)[number];\n\n// Why a ghost's removal was refused, in the refusal's details, so the client answers each one: the\n// ghost has played (link it instead) or its removal stopped on finding it had; a game the removal\n// needs is held by another operation (try again shortly); the ghost is being, or was, linked; the\n// ghost is the team's captain (change the captain first).\nexport const GHOST_REMOVAL_REFUSAL_KEYS = [\n 'ghostHasPlayed',\n 'removalStopped',\n 'gameHeld',\n 'ghostBeingLinked',\n 'captainNotRemovable',\n] as const;\nexport type GhostRemovalRefusal = (typeof GHOST_REMOVAL_REFUSAL_KEYS)[number];\n"]}
|
package/dist/types/unions.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Canonical unions (ARCH-102): an `as const` key array with the type derived from it. Zod enums,
|
|
1
|
+
// Canonical unions (RULE-STD-ARCH-102): an `as const` key array with the type derived from it. Zod enums,
|
|
2
2
|
// type positions, query filters, and option lists all derive from these arrays — never a quoted
|
|
3
3
|
// member.
|
|
4
4
|
// The two global roles. Each is a roster on `_systemData/adminList` and a boolean custom claim of
|
|
@@ -42,7 +42,7 @@ export function higherTeamRole(left, right) {
|
|
|
42
42
|
}
|
|
43
43
|
export const TEAM_MEMBERSHIP_STATUS_KEYS = ['active'];
|
|
44
44
|
// The status a membership grants authority in. Every membership-based check reads it with the role
|
|
45
|
-
// (BACKEND-
|
|
45
|
+
// (RULE-QS-BACKEND-901), so a status added later grants nothing until a check names it.
|
|
46
46
|
export const ACTIVE_TEAM_MEMBERSHIP_STATUS = 'active';
|
|
47
47
|
// How a membership came to exist; absent on a membership whose provenance was never recorded.
|
|
48
48
|
export const TEAM_JOIN_METHOD_KEYS = [
|
package/dist/types/unions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unions.js","sourceRoot":"","sources":["../../src/types/unions.ts"],"names":[],"mappings":"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","sourcesContent":["// Canonical unions (ARCH-102): an `as const` key array with the type derived from it. Zod enums,\n// type positions, query filters, and option lists all derive from these arrays — never a quoted\n// member.\n\n// The two global roles. Each is a roster on `_systemData/adminList` and a boolean custom claim of\n// the same name; the roster is the authority, the claim a fast hint.\nexport const SYSTEM_ROLE_KEYS = ['admin', 'referee'] as const;\nexport type SystemRole = (typeof SYSTEM_ROLE_KEYS)[number];\n\n// Account status on the private profile. Only an exact `active` passes the server auth assertion.\nexport const USER_STATUS_KEYS = ['active', 'banned'] as const;\nexport type UserStatus = (typeof USER_STATUS_KEYS)[number];\n/** The one status that lets an account act. */\nexport const ACTIVE_USER_STATUS = 'active' satisfies UserStatus;\n/** The status an admin's ban sets: the account keeps its data and cannot sign in. */\nexport const BANNED_USER_STATUS = 'banned' satisfies UserStatus;\n\n// Which post-commit Auth effect queued an account on `statusReconcileQueue/{userId}`:\n// `accountStatus` — a status change's disabled flag, status claim, and token revocation, queued in\n// the status transaction itself; `roleClaims` — the `admin` / `referee` claims after a failed roster\n// claim write.\nexport const STATUS_RECONCILE_QUEUE_AUTH_EFFECTS = ['accountStatus', 'roleClaims'] as const;\nexport type StatusReconcileQueueAuthEffect = (typeof STATUS_RECONCILE_QUEUE_AUTH_EFFECTS)[number];\nexport const ACCOUNT_STATUS_AUTH_EFFECT =\n 'accountStatus' as const satisfies StatusReconcileQueueAuthEffect;\nexport const ROLE_CLAIMS_EFFECT = 'roleClaims' as const satisfies StatusReconcileQueueAuthEffect;\n\nexport const TEAM_ROLE_KEYS = ['captain', 'coCaptain', 'player'] as const;\nexport type TeamRole = (typeof TEAM_ROLE_KEYS)[number];\n\n// The roles that carry captain authority. `firestore.rules` restates this list, because a rules file\n// cannot import it.\nexport const CAPTAIN_TEAM_ROLES = ['captain', 'coCaptain'] as const satisfies readonly TeamRole[];\n\n// The one role a team holds at most one of: team creation, the admin captain change, and ghost\n// linking write it, and nothing else does.\nexport const TEAM_CAPTAIN_ROLE = 'captain' as const satisfies TeamRole;\n\n// The two roles below the captain. A co-captain holds every captain power except managing\n// co-captains; a player holds none.\nexport const TEAM_CO_CAPTAIN_ROLE = 'coCaptain' as const satisfies TeamRole;\nexport const TEAM_PLAYER_ROLE = 'player' as const satisfies TeamRole;\n\n// The roles a member's role change moves a membership between — promoting a player to co-captain,\n// or demoting a co-captain to player. The captain's role moves only through the admin's captain\n// change, so it is never one of them.\nexport const MEMBER_ASSIGNABLE_TEAM_ROLES = [\n TEAM_CO_CAPTAIN_ROLE,\n TEAM_PLAYER_ROLE,\n] as const satisfies readonly TeamRole[];\nexport type MemberAssignableTeamRole = (typeof MEMBER_ASSIGNABLE_TEAM_ROLES)[number];\n\n// A ghost link that merges a ghost's membership into the account's keeps one membership with the\n// higher of the two roles: `TEAM_ROLE_KEYS` runs from the highest role down.\nexport function higherTeamRole(left: TeamRole, right: TeamRole): TeamRole {\n return TEAM_ROLE_KEYS.indexOf(left) <= TEAM_ROLE_KEYS.indexOf(right) ? left : right;\n}\n\nexport const TEAM_MEMBERSHIP_STATUS_KEYS = ['active'] as const;\nexport type TeamMembershipStatus = (typeof TEAM_MEMBERSHIP_STATUS_KEYS)[number];\n\n// The status a membership grants authority in. Every membership-based check reads it with the role\n// (BACKEND-006), so a status added later grants nothing until a check names it.\nexport const ACTIVE_TEAM_MEMBERSHIP_STATUS = 'active' as const satisfies TeamMembershipStatus;\n\n// How a membership came to exist; absent on a membership whose provenance was never recorded.\nexport const TEAM_JOIN_METHOD_KEYS = [\n 'teamCreation',\n 'invite',\n 'joinRequest',\n 'freeAgent',\n 'ghostAdd',\n] as const;\nexport type TeamJoinMethod = (typeof TEAM_JOIN_METHOD_KEYS)[number];\n\nexport const LEAGUE_STATUS_KEYS = ['pending', 'upcoming', 'active', 'closed'] as const;\nexport type LeagueStatus = (typeof LEAGUE_STATUS_KEYS)[number];\n\n// Every league is created unpublished; the admin moves it forward from here.\nexport const LEAGUE_STATUS_ON_CREATE = 'pending' as const satisfies LeagueStatus;\n\n// A finished season. Its settings stay editable; its status and mode never change again.\nexport const CLOSED_LEAGUE_STATUS = 'closed' as const satisfies LeagueStatus;\n\n// The two published statuses before a league closes: its teams are forming, then it is in play.\nexport const UPCOMING_LEAGUE_STATUS = 'upcoming' as const satisfies LeagueStatus;\nexport const ACTIVE_LEAGUE_STATUS = 'active' as const satisfies LeagueStatus;\n\n// The statuses a league may move to from each status. Movement is forward only, and `closed` is\n// final; the status callable refuses any other move.\nexport const LEAGUE_STATUS_TRANSITIONS: Readonly<Record<LeagueStatus, readonly LeagueStatus[]>> = {\n pending: ['upcoming', 'closed'],\n upcoming: ['active', 'closed'],\n active: ['closed'],\n closed: [],\n};\n\n// Every status but closed: a league still being set up, published, or played. Whatever such a\n// league is configured with — its waiver template among them — is still in use.\nexport const OPEN_LEAGUE_STATUS_KEYS: readonly Exclude<\n LeagueStatus,\n typeof CLOSED_LEAGUE_STATUS\n>[] = LEAGUE_STATUS_KEYS.filter(\n (status): status is Exclude<LeagueStatus, typeof CLOSED_LEAGUE_STATUS> =>\n status !== CLOSED_LEAGUE_STATUS,\n);\n\n// A league players are part of now or next: published and not yet closed. The admin dashboard's\n// active free-agent count covers only these leagues.\nexport const CURRENT_LEAGUE_STATUS_KEYS = [\n UPCOMING_LEAGUE_STATUS,\n ACTIVE_LEAGUE_STATUS,\n] as const satisfies readonly LeagueStatus[];\n\nexport const LEAGUE_MODE_KEYS = ['Regular', 'Competitive/Recreational'] as const;\nexport type LeagueMode = (typeof LEAGUE_MODE_KEYS)[number];\n\n// Present only on teams in a Competitive/Recreational league. In any other mode a team has no type:\n// the field is absent, never null.\nexport const TEAM_TYPE_KEYS = ['Competitive', 'Recreational'] as const;\nexport type TeamType = (typeof TEAM_TYPE_KEYS)[number];\n\n// The one mode whose teams each carry a `teamType`.\nexport const TEAM_TYPED_LEAGUE_MODE = 'Competitive/Recreational' as const satisfies LeagueMode;\n\n// The type every team takes when its league switches into `TEAM_TYPED_LEAGUE_MODE`.\nexport const TEAM_TYPE_ON_MODE_SWITCH = 'Recreational' as const satisfies TeamType;\n\nexport const GAME_STATUS_KEYS = ['scheduled', 'inprogress', 'completed'] as const;\nexport type GameStatus = (typeof GAME_STATUS_KEYS)[number];\n\n// The one status a finished game holds: it was played, and its stats count. Every reader asking\n// whether a game was played compares against this rather than naming a status of its own.\nexport const COMPLETED_GAME_STATUS = 'completed' as const satisfies GameStatus;\n\n// The status a newly scheduled game is created in.\nexport const GAME_STATUS_ON_CREATE = 'scheduled' as const satisfies GameStatus;\n\n// The status reopen returns a finalized game to: open for scoring again, its record of who played\n// kept.\nexport const GAME_STATUS_ON_REOPEN = 'inprogress' as const satisfies GameStatus;\n\n// An invitation is pending until the invitee accepts (`approved`) or declines (`rejected`) it, or the\n// team withdraws it (`cancelled`). A membership on its team made any other way closes it `approved`.\nexport const TEAM_INVITATION_STATUS_KEYS = [\n 'pending',\n 'approved',\n 'rejected',\n 'cancelled',\n] as const;\nexport type TeamInvitationStatus = (typeof TEAM_INVITATION_STATUS_KEYS)[number];\n\nexport const PENDING_TEAM_INVITATION_STATUS = 'pending' as const satisfies TeamInvitationStatus;\nexport const APPROVED_TEAM_INVITATION_STATUS = 'approved' as const satisfies TeamInvitationStatus;\nexport const REJECTED_TEAM_INVITATION_STATUS = 'rejected' as const satisfies TeamInvitationStatus;\nexport const CANCELLED_TEAM_INVITATION_STATUS = 'cancelled' as const satisfies TeamInvitationStatus;\n\n// A join request is pending until the team's leaders accept (`approved`) or reject (`rejected`) it,\n// or the requester withdraws it (`cancelled`). A membership on its team made any other way closes it\n// `approved`.\nexport const TEAM_JOIN_REQUEST_STATUS_KEYS = [\n 'pending',\n 'approved',\n 'rejected',\n 'cancelled',\n] as const;\nexport type TeamJoinRequestStatus = (typeof TEAM_JOIN_REQUEST_STATUS_KEYS)[number];\n\nexport const PENDING_TEAM_JOIN_REQUEST_STATUS = 'pending' as const satisfies TeamJoinRequestStatus;\nexport const APPROVED_TEAM_JOIN_REQUEST_STATUS =\n 'approved' as const satisfies TeamJoinRequestStatus;\nexport const REJECTED_TEAM_JOIN_REQUEST_STATUS =\n 'rejected' as const satisfies TeamJoinRequestStatus;\nexport const CANCELLED_TEAM_JOIN_REQUEST_STATUS =\n 'cancelled' as const satisfies TeamJoinRequestStatus;\n\nexport const HARDWARE_LOAN_CONTRACT_STATUS_KEYS = ['pending', 'loaned', 'returned'] as const;\nexport type HardwareLoanContractStatus = (typeof HARDWARE_LOAN_CONTRACT_STATUS_KEYS)[number];\n// Why an award grant passed over an account it named: it has no profile, or it is a ghost, which\n// holds no account.\nexport const AWARD_GRANT_SKIP_REASON_KEYS = ['noProfile', 'ghost'] as const;\nexport type AwardGrantSkipReason = (typeof AWARD_GRANT_SKIP_REASON_KEYS)[number];\n\n// The two badges an account shows beside its name.\nexport const FEATURED_AWARD_SLOT_KEYS = ['primary', 'secondary'] as const;\nexport type FeaturedAwardSlot = (typeof FEATURED_AWARD_SLOT_KEYS)[number];\n\n// The groups an award is granted to all at once: every active member of a team, or of a league.\nexport const AWARD_GROUP_TYPE_KEYS = ['team', 'league'] as const;\nexport type AwardGroupType = (typeof AWARD_GROUP_TYPE_KEYS)[number];\n\n// A decision on one award for one group: grant it to the group's people, or take back what the\n// group's grants gave.\nexport const AWARD_GROUP_GRANT_ACTION_KEYS = ['grant', 'revoke'] as const;\nexport type AwardGroupGrantAction = (typeof AWARD_GROUP_GRANT_ACTION_KEYS)[number];\n\n// A decision is `pending` until every page of it is done, then `complete`.\nexport const AWARD_GROUP_GRANT_STATUS_KEYS = ['pending', 'complete'] as const;\nexport type AwardGroupGrantStatus = (typeof AWARD_GROUP_GRANT_STATUS_KEYS)[number];\n\n// Why taking a group's award back left one person holding it: they held it before the grant reached\n// them, or another group's grant still holds it for them.\nexport const AWARD_GROUP_REVOKE_SKIP_KEYS = ['heldBefore', 'heldByAnotherGrant'] as const;\nexport type AwardGroupRevokeSkip = (typeof AWARD_GROUP_REVOKE_SKIP_KEYS)[number];\n\nexport const PENDING_HARDWARE_LOAN_CONTRACT_STATUS =\n 'pending' as const satisfies HardwareLoanContractStatus;\nexport const LOANED_HARDWARE_LOAN_CONTRACT_STATUS =\n 'loaned' as const satisfies HardwareLoanContractStatus;\nexport const RETURNED_HARDWARE_LOAN_CONTRACT_STATUS =\n 'returned' as const satisfies HardwareLoanContractStatus;\n\n// What deleting a waiver template did. A template nothing names is deleted with its versions; one a\n// signature or a closed league still names is retired — kept for them, offered to no new league.\nexport const WAIVER_TEMPLATE_DELETE_OUTCOME_KEYS = ['deleted', 'retired'] as const;\nexport type WaiverTemplateDeleteOutcome = (typeof WAIVER_TEMPLATE_DELETE_OUTCOME_KEYS)[number];\n\n// What last changed the stats, as announced on the stats beacon; `link` is a ghost link moving a\n// game's lines onto an account.\nexport const STATS_BEACON_ACTION_KEYS = [\n 'finalize',\n 'reopen',\n 'recalculate',\n 'correct',\n 'historical-update',\n 'link',\n] as const;\nexport type StatsBeaconAction = (typeof STATS_BEACON_ACTION_KEYS)[number];\n\n// The actions that describe one game, so a beacon announcing one names the game, its league, and its\n// teams; every other action names no game, and a game id left beside it would point at a stale one.\nexport const GAME_SCOPED_STATS_BEACON_ACTION_KEYS = [\n 'finalize',\n 'reopen',\n] as const satisfies readonly StatsBeaconAction[];\nexport type GameScopedStatsBeaconAction = (typeof GAME_SCOPED_STATS_BEACON_ACTION_KEYS)[number];\n\n// The statuses a game's roster still follows its teams' memberships in: listed explicitly, so a\n// status added later is closed until it is named here, never open by default.\nexport const OPEN_GAME_STATUS_KEYS = [\n 'scheduled',\n 'inprogress',\n] as const satisfies readonly GameStatus[];\nexport type OpenGameStatus = (typeof OPEN_GAME_STATUS_KEYS)[number];\n\n// Whether a game is still open — not yet finalized — so a scorer may still change it. Both app roots\n// ask this one predicate.\nexport function isOpenGameStatus(status: GameStatus): status is OpenGameStatus {\n return (OPEN_GAME_STATUS_KEYS as readonly GameStatus[]).includes(status);\n}\n\n// Where one membership's roster obligation stands. `pending` waits for the reconciliation worker;\n// `failed` has spent its retries and waits for an admin's retry; `reconciled` owes nothing.\nexport const MEMBERSHIP_ROSTER_SYNC_STATUS_KEYS = ['pending', 'reconciled', 'failed'] as const;\nexport type MembershipRosterSyncStatus = (typeof MEMBERSHIP_ROSTER_SYNC_STATUS_KEYS)[number];\nexport const PENDING_ROSTER_SYNC_STATUS = 'pending' as const satisfies MembershipRosterSyncStatus;\nexport const RECONCILED_ROSTER_SYNC_STATUS =\n 'reconciled' as const satisfies MembershipRosterSyncStatus;\nexport const FAILED_ROSTER_SYNC_STATUS = 'failed' as const satisfies MembershipRosterSyncStatus;\n\n// The authority a ghost's waiver was signed under: the witness's captaincy on the ghost's team, or\n// the global role the admin entry confirmed.\nexport const WAIVER_WITNESS_AUTHORITY_KEYS = ['captain', 'coCaptain', 'admin', 'referee'] as const;\nexport type WaiverWitnessAuthority = (typeof WAIVER_WITNESS_AUTHORITY_KEYS)[number];\n\n// Why a signing was refused, named in its details so the signing dialog answers it: `waiverChanged`\n// when the wording the signer saw — the template id and version the dialog sent — is no longer the\n// league's, so the dialog loads the current wording to read again.\nexport const WAIVER_SIGNING_REFUSAL_KEYS = ['waiverChanged'] as const;\nexport type WaiverSigningRefusal = (typeof WAIVER_SIGNING_REFUSAL_KEYS)[number];\n\n// Why a waiver-template publication was refused, named in its details so the editor answers it:\n// `templateVersionChanged` when the version the editor loaded is no longer the template's current\n// one, so the editor keeps the admin's draft and shows the newer wording before publishing again.\nexport const WAIVER_TEMPLATE_EDIT_REFUSAL_KEYS = ['templateVersionChanged'] as const;\nexport type WaiverTemplateEditRefusal = (typeof WAIVER_TEMPLATE_EDIT_REFUSAL_KEYS)[number];\n\n// The icon a team picks at creation; the persisted value is the icon component's name.\nexport const TEAM_ICON_KEYS = [\n 'Shield',\n 'Swords',\n 'Skull',\n 'Ghost',\n 'Cat',\n 'Dog',\n 'Bird',\n 'Fish',\n 'Rabbit',\n 'Snail',\n 'Turtle',\n 'Cherry',\n 'Apple',\n 'Grape',\n 'Rocket',\n 'Plane',\n 'Ship',\n 'Train',\n 'Car',\n 'Bike',\n 'Bolt',\n 'Star',\n 'Sun',\n 'Moon',\n 'Cloud',\n 'Crown',\n 'Diamond',\n 'Gem',\n 'Anchor',\n // Appended — the set only grows, and no stored key is ever renamed or removed. Seasonal and events.\n 'TreePine',\n 'Trees',\n 'TreeDeciduous',\n 'TreePalm',\n 'Snowflake',\n 'MountainSnow',\n 'Gift',\n 'PartyPopper',\n 'CandyCane',\n 'Candy',\n 'Lollipop',\n 'Cake',\n 'Egg',\n 'Clover',\n 'Heart',\n 'Flower',\n 'Flower2',\n 'Rose',\n 'Leaf',\n 'Sprout',\n 'Wheat',\n 'Sunrise',\n 'Rainbow',\n 'Bell',\n // Awards and sport.\n 'Trophy',\n 'Medal',\n 'Award',\n 'Ribbon',\n 'Flag',\n 'Target',\n 'Crosshair',\n 'Goal',\n 'Dumbbell',\n 'Footprints',\n // Power and the elements.\n 'Zap',\n 'Flame',\n 'FlameKindling',\n 'Bomb',\n 'Atom',\n 'Orbit',\n 'Sparkles',\n 'WandSparkles',\n 'Mountain',\n 'Tornado',\n 'Wind',\n 'Droplet',\n 'CloudLightning',\n 'MoonStar',\n // Arms and strongholds.\n 'Sword',\n 'Axe',\n 'Hammer',\n 'Pickaxe',\n 'ShieldHalf',\n 'Castle',\n // Animals.\n 'Squirrel',\n 'Rat',\n 'Panda',\n 'Shrimp',\n 'Worm',\n 'Bug',\n 'Shell',\n 'PawPrint',\n 'Feather',\n 'Bone',\n 'Origami',\n // Food.\n 'Citrus',\n 'Banana',\n 'Carrot',\n 'Pizza',\n 'Cookie',\n 'Donut',\n 'Coffee',\n // Games and music.\n 'Dices',\n 'Puzzle',\n 'Gamepad2',\n 'Spade',\n 'Club',\n 'Music',\n 'Guitar',\n 'Hexagon',\n 'Triangle',\n // Travel.\n 'Sailboat',\n 'Tractor',\n 'Truck',\n] as const;\nexport type TeamIcon = (typeof TEAM_ICON_KEYS)[number];\n\n// A picture's processed sizes, smallest first: every picture kind declares all three, and a display\n// asks for the smallest one that covers its slot.\nexport const PICTURE_VARIANT_KEYS = ['sm', 'md', 'lg'] as const;\nexport type PictureVariantKey = (typeof PICTURE_VARIANT_KEYS)[number];\n\n// What a stats check found, game tier first — a game's own numbers are the cause of the aggregate\n// findings, so Fix stats repairs games before it rebuilds what they feed.\nexport const GAME_TIER_DISCREPANCY_KIND_KEYS = [\n // A game whose document the check could not read: nothing else about it could be checked.\n 'gameUnreadable',\n 'invalidEvent',\n 'eventSequenceMismatch',\n // A game whose events do not hold exactly the sequences 1..n: a gap or a duplicate.\n 'eventSequenceGap',\n 'rollupMismatch',\n 'scoreMirrorMismatch',\n 'unrosteredStatLine',\n 'fantasyPointsStale',\n 'finalRecordMissing',\n 'finalRecordMismatch',\n 'participationSnapshotMismatch',\n 'gameHeld',\n] as const;\nexport const AGGREGATE_TIER_DISCREPANCY_KIND_KEYS = [\n 'aggregateMismatch',\n 'aggregateEntryStale',\n 'aggregateEntryMissing',\n 'hallOfFameLifetimeMismatch',\n] as const;\nexport const STATS_DISCREPANCY_KIND_KEYS = [\n ...GAME_TIER_DISCREPANCY_KIND_KEYS,\n ...AGGREGATE_TIER_DISCREPANCY_KIND_KEYS,\n] as const;\nexport type StatsDiscrepancyKind = (typeof STATS_DISCREPANCY_KIND_KEYS)[number];\n"]}
|
|
1
|
+
{"version":3,"file":"unions.js","sourceRoot":"","sources":["../../src/types/unions.ts"],"names":[],"mappings":"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","sourcesContent":["// Canonical unions (RULE-STD-ARCH-102): an `as const` key array with the type derived from it. Zod enums,\n// type positions, query filters, and option lists all derive from these arrays — never a quoted\n// member.\n\n// The two global roles. Each is a roster on `_systemData/adminList` and a boolean custom claim of\n// the same name; the roster is the authority, the claim a fast hint.\nexport const SYSTEM_ROLE_KEYS = ['admin', 'referee'] as const;\nexport type SystemRole = (typeof SYSTEM_ROLE_KEYS)[number];\n\n// Account status on the private profile. Only an exact `active` passes the server auth assertion.\nexport const USER_STATUS_KEYS = ['active', 'banned'] as const;\nexport type UserStatus = (typeof USER_STATUS_KEYS)[number];\n/** The one status that lets an account act. */\nexport const ACTIVE_USER_STATUS = 'active' satisfies UserStatus;\n/** The status an admin's ban sets: the account keeps its data and cannot sign in. */\nexport const BANNED_USER_STATUS = 'banned' satisfies UserStatus;\n\n// Which post-commit Auth effect queued an account on `statusReconcileQueue/{userId}`:\n// `accountStatus` — a status change's disabled flag, status claim, and token revocation, queued in\n// the status transaction itself; `roleClaims` — the `admin` / `referee` claims after a failed roster\n// claim write.\nexport const STATUS_RECONCILE_QUEUE_AUTH_EFFECTS = ['accountStatus', 'roleClaims'] as const;\nexport type StatusReconcileQueueAuthEffect = (typeof STATUS_RECONCILE_QUEUE_AUTH_EFFECTS)[number];\nexport const ACCOUNT_STATUS_AUTH_EFFECT =\n 'accountStatus' as const satisfies StatusReconcileQueueAuthEffect;\nexport const ROLE_CLAIMS_EFFECT = 'roleClaims' as const satisfies StatusReconcileQueueAuthEffect;\n\nexport const TEAM_ROLE_KEYS = ['captain', 'coCaptain', 'player'] as const;\nexport type TeamRole = (typeof TEAM_ROLE_KEYS)[number];\n\n// The roles that carry captain authority. `firestore.rules` restates this list, because a rules file\n// cannot import it.\nexport const CAPTAIN_TEAM_ROLES = ['captain', 'coCaptain'] as const satisfies readonly TeamRole[];\n\n// The one role a team holds at most one of: team creation, the admin captain change, and ghost\n// linking write it, and nothing else does.\nexport const TEAM_CAPTAIN_ROLE = 'captain' as const satisfies TeamRole;\n\n// The two roles below the captain. A co-captain holds every captain power except managing\n// co-captains; a player holds none.\nexport const TEAM_CO_CAPTAIN_ROLE = 'coCaptain' as const satisfies TeamRole;\nexport const TEAM_PLAYER_ROLE = 'player' as const satisfies TeamRole;\n\n// The roles a member's role change moves a membership between — promoting a player to co-captain,\n// or demoting a co-captain to player. The captain's role moves only through the admin's captain\n// change, so it is never one of them.\nexport const MEMBER_ASSIGNABLE_TEAM_ROLES = [\n TEAM_CO_CAPTAIN_ROLE,\n TEAM_PLAYER_ROLE,\n] as const satisfies readonly TeamRole[];\nexport type MemberAssignableTeamRole = (typeof MEMBER_ASSIGNABLE_TEAM_ROLES)[number];\n\n// A ghost link that merges a ghost's membership into the account's keeps one membership with the\n// higher of the two roles: `TEAM_ROLE_KEYS` runs from the highest role down.\nexport function higherTeamRole(left: TeamRole, right: TeamRole): TeamRole {\n return TEAM_ROLE_KEYS.indexOf(left) <= TEAM_ROLE_KEYS.indexOf(right) ? left : right;\n}\n\nexport const TEAM_MEMBERSHIP_STATUS_KEYS = ['active'] as const;\nexport type TeamMembershipStatus = (typeof TEAM_MEMBERSHIP_STATUS_KEYS)[number];\n\n// The status a membership grants authority in. Every membership-based check reads it with the role\n// (RULE-QS-BACKEND-901), so a status added later grants nothing until a check names it.\nexport const ACTIVE_TEAM_MEMBERSHIP_STATUS = 'active' as const satisfies TeamMembershipStatus;\n\n// How a membership came to exist; absent on a membership whose provenance was never recorded.\nexport const TEAM_JOIN_METHOD_KEYS = [\n 'teamCreation',\n 'invite',\n 'joinRequest',\n 'freeAgent',\n 'ghostAdd',\n] as const;\nexport type TeamJoinMethod = (typeof TEAM_JOIN_METHOD_KEYS)[number];\n\nexport const LEAGUE_STATUS_KEYS = ['pending', 'upcoming', 'active', 'closed'] as const;\nexport type LeagueStatus = (typeof LEAGUE_STATUS_KEYS)[number];\n\n// Every league is created unpublished; the admin moves it forward from here.\nexport const LEAGUE_STATUS_ON_CREATE = 'pending' as const satisfies LeagueStatus;\n\n// A finished season. Its settings stay editable; its status and mode never change again.\nexport const CLOSED_LEAGUE_STATUS = 'closed' as const satisfies LeagueStatus;\n\n// The two published statuses before a league closes: its teams are forming, then it is in play.\nexport const UPCOMING_LEAGUE_STATUS = 'upcoming' as const satisfies LeagueStatus;\nexport const ACTIVE_LEAGUE_STATUS = 'active' as const satisfies LeagueStatus;\n\n// The statuses a league may move to from each status. Movement is forward only, and `closed` is\n// final; the status callable refuses any other move.\nexport const LEAGUE_STATUS_TRANSITIONS: Readonly<Record<LeagueStatus, readonly LeagueStatus[]>> = {\n pending: ['upcoming', 'closed'],\n upcoming: ['active', 'closed'],\n active: ['closed'],\n closed: [],\n};\n\n// Every status but closed: a league still being set up, published, or played. Whatever such a\n// league is configured with — its waiver template among them — is still in use.\nexport const OPEN_LEAGUE_STATUS_KEYS: readonly Exclude<\n LeagueStatus,\n typeof CLOSED_LEAGUE_STATUS\n>[] = LEAGUE_STATUS_KEYS.filter(\n (status): status is Exclude<LeagueStatus, typeof CLOSED_LEAGUE_STATUS> =>\n status !== CLOSED_LEAGUE_STATUS,\n);\n\n// A league players are part of now or next: published and not yet closed. The admin dashboard's\n// active free-agent count covers only these leagues.\nexport const CURRENT_LEAGUE_STATUS_KEYS = [\n UPCOMING_LEAGUE_STATUS,\n ACTIVE_LEAGUE_STATUS,\n] as const satisfies readonly LeagueStatus[];\n\nexport const LEAGUE_MODE_KEYS = ['Regular', 'Competitive/Recreational'] as const;\nexport type LeagueMode = (typeof LEAGUE_MODE_KEYS)[number];\n\n// Present only on teams in a Competitive/Recreational league. In any other mode a team has no type:\n// the field is absent, never null.\nexport const TEAM_TYPE_KEYS = ['Competitive', 'Recreational'] as const;\nexport type TeamType = (typeof TEAM_TYPE_KEYS)[number];\n\n// The one mode whose teams each carry a `teamType`.\nexport const TEAM_TYPED_LEAGUE_MODE = 'Competitive/Recreational' as const satisfies LeagueMode;\n\n// The type every team takes when its league switches into `TEAM_TYPED_LEAGUE_MODE`.\nexport const TEAM_TYPE_ON_MODE_SWITCH = 'Recreational' as const satisfies TeamType;\n\nexport const GAME_STATUS_KEYS = ['scheduled', 'inprogress', 'completed'] as const;\nexport type GameStatus = (typeof GAME_STATUS_KEYS)[number];\n\n// The one status a finished game holds: it was played, and its stats count. Every reader asking\n// whether a game was played compares against this rather than naming a status of its own.\nexport const COMPLETED_GAME_STATUS = 'completed' as const satisfies GameStatus;\n\n// The status a newly scheduled game is created in.\nexport const GAME_STATUS_ON_CREATE = 'scheduled' as const satisfies GameStatus;\n\n// The status reopen returns a finalized game to: open for scoring again, its record of who played\n// kept.\nexport const GAME_STATUS_ON_REOPEN = 'inprogress' as const satisfies GameStatus;\n\n// An invitation is pending until the invitee accepts (`approved`) or declines (`rejected`) it, or the\n// team withdraws it (`cancelled`). A membership on its team made any other way closes it `approved`.\nexport const TEAM_INVITATION_STATUS_KEYS = [\n 'pending',\n 'approved',\n 'rejected',\n 'cancelled',\n] as const;\nexport type TeamInvitationStatus = (typeof TEAM_INVITATION_STATUS_KEYS)[number];\n\nexport const PENDING_TEAM_INVITATION_STATUS = 'pending' as const satisfies TeamInvitationStatus;\nexport const APPROVED_TEAM_INVITATION_STATUS = 'approved' as const satisfies TeamInvitationStatus;\nexport const REJECTED_TEAM_INVITATION_STATUS = 'rejected' as const satisfies TeamInvitationStatus;\nexport const CANCELLED_TEAM_INVITATION_STATUS = 'cancelled' as const satisfies TeamInvitationStatus;\n\n// A join request is pending until the team's leaders accept (`approved`) or reject (`rejected`) it,\n// or the requester withdraws it (`cancelled`). A membership on its team made any other way closes it\n// `approved`.\nexport const TEAM_JOIN_REQUEST_STATUS_KEYS = [\n 'pending',\n 'approved',\n 'rejected',\n 'cancelled',\n] as const;\nexport type TeamJoinRequestStatus = (typeof TEAM_JOIN_REQUEST_STATUS_KEYS)[number];\n\nexport const PENDING_TEAM_JOIN_REQUEST_STATUS = 'pending' as const satisfies TeamJoinRequestStatus;\nexport const APPROVED_TEAM_JOIN_REQUEST_STATUS =\n 'approved' as const satisfies TeamJoinRequestStatus;\nexport const REJECTED_TEAM_JOIN_REQUEST_STATUS =\n 'rejected' as const satisfies TeamJoinRequestStatus;\nexport const CANCELLED_TEAM_JOIN_REQUEST_STATUS =\n 'cancelled' as const satisfies TeamJoinRequestStatus;\n\nexport const HARDWARE_LOAN_CONTRACT_STATUS_KEYS = ['pending', 'loaned', 'returned'] as const;\nexport type HardwareLoanContractStatus = (typeof HARDWARE_LOAN_CONTRACT_STATUS_KEYS)[number];\n// Why an award grant passed over an account it named: it has no profile, or it is a ghost, which\n// holds no account.\nexport const AWARD_GRANT_SKIP_REASON_KEYS = ['noProfile', 'ghost'] as const;\nexport type AwardGrantSkipReason = (typeof AWARD_GRANT_SKIP_REASON_KEYS)[number];\n\n// The two badges an account shows beside its name.\nexport const FEATURED_AWARD_SLOT_KEYS = ['primary', 'secondary'] as const;\nexport type FeaturedAwardSlot = (typeof FEATURED_AWARD_SLOT_KEYS)[number];\n\n// The groups an award is granted to all at once: every active member of a team, or of a league.\nexport const AWARD_GROUP_TYPE_KEYS = ['team', 'league'] as const;\nexport type AwardGroupType = (typeof AWARD_GROUP_TYPE_KEYS)[number];\n\n// A decision on one award for one group: grant it to the group's people, or take back what the\n// group's grants gave.\nexport const AWARD_GROUP_GRANT_ACTION_KEYS = ['grant', 'revoke'] as const;\nexport type AwardGroupGrantAction = (typeof AWARD_GROUP_GRANT_ACTION_KEYS)[number];\n\n// A decision is `pending` until every page of it is done, then `complete`.\nexport const AWARD_GROUP_GRANT_STATUS_KEYS = ['pending', 'complete'] as const;\nexport type AwardGroupGrantStatus = (typeof AWARD_GROUP_GRANT_STATUS_KEYS)[number];\n\n// Why taking a group's award back left one person holding it: they held it before the grant reached\n// them, or another group's grant still holds it for them.\nexport const AWARD_GROUP_REVOKE_SKIP_KEYS = ['heldBefore', 'heldByAnotherGrant'] as const;\nexport type AwardGroupRevokeSkip = (typeof AWARD_GROUP_REVOKE_SKIP_KEYS)[number];\n\nexport const PENDING_HARDWARE_LOAN_CONTRACT_STATUS =\n 'pending' as const satisfies HardwareLoanContractStatus;\nexport const LOANED_HARDWARE_LOAN_CONTRACT_STATUS =\n 'loaned' as const satisfies HardwareLoanContractStatus;\nexport const RETURNED_HARDWARE_LOAN_CONTRACT_STATUS =\n 'returned' as const satisfies HardwareLoanContractStatus;\n\n// What deleting a waiver template did. A template nothing names is deleted with its versions; one a\n// signature or a closed league still names is retired — kept for them, offered to no new league.\nexport const WAIVER_TEMPLATE_DELETE_OUTCOME_KEYS = ['deleted', 'retired'] as const;\nexport type WaiverTemplateDeleteOutcome = (typeof WAIVER_TEMPLATE_DELETE_OUTCOME_KEYS)[number];\n\n// What last changed the stats, as announced on the stats beacon; `link` is a ghost link moving a\n// game's lines onto an account.\nexport const STATS_BEACON_ACTION_KEYS = [\n 'finalize',\n 'reopen',\n 'recalculate',\n 'correct',\n 'historical-update',\n 'link',\n] as const;\nexport type StatsBeaconAction = (typeof STATS_BEACON_ACTION_KEYS)[number];\n\n// The actions that describe one game, so a beacon announcing one names the game, its league, and its\n// teams; every other action names no game, and a game id left beside it would point at a stale one.\nexport const GAME_SCOPED_STATS_BEACON_ACTION_KEYS = [\n 'finalize',\n 'reopen',\n] as const satisfies readonly StatsBeaconAction[];\nexport type GameScopedStatsBeaconAction = (typeof GAME_SCOPED_STATS_BEACON_ACTION_KEYS)[number];\n\n// The statuses a game's roster still follows its teams' memberships in: listed explicitly, so a\n// status added later is closed until it is named here, never open by default.\nexport const OPEN_GAME_STATUS_KEYS = [\n 'scheduled',\n 'inprogress',\n] as const satisfies readonly GameStatus[];\nexport type OpenGameStatus = (typeof OPEN_GAME_STATUS_KEYS)[number];\n\n// Whether a game is still open — not yet finalized — so a scorer may still change it. Both app roots\n// ask this one predicate.\nexport function isOpenGameStatus(status: GameStatus): status is OpenGameStatus {\n return (OPEN_GAME_STATUS_KEYS as readonly GameStatus[]).includes(status);\n}\n\n// Where one membership's roster obligation stands. `pending` waits for the reconciliation worker;\n// `failed` has spent its retries and waits for an admin's retry; `reconciled` owes nothing.\nexport const MEMBERSHIP_ROSTER_SYNC_STATUS_KEYS = ['pending', 'reconciled', 'failed'] as const;\nexport type MembershipRosterSyncStatus = (typeof MEMBERSHIP_ROSTER_SYNC_STATUS_KEYS)[number];\nexport const PENDING_ROSTER_SYNC_STATUS = 'pending' as const satisfies MembershipRosterSyncStatus;\nexport const RECONCILED_ROSTER_SYNC_STATUS =\n 'reconciled' as const satisfies MembershipRosterSyncStatus;\nexport const FAILED_ROSTER_SYNC_STATUS = 'failed' as const satisfies MembershipRosterSyncStatus;\n\n// The authority a ghost's waiver was signed under: the witness's captaincy on the ghost's team, or\n// the global role the admin entry confirmed.\nexport const WAIVER_WITNESS_AUTHORITY_KEYS = ['captain', 'coCaptain', 'admin', 'referee'] as const;\nexport type WaiverWitnessAuthority = (typeof WAIVER_WITNESS_AUTHORITY_KEYS)[number];\n\n// Why a signing was refused, named in its details so the signing dialog answers it: `waiverChanged`\n// when the wording the signer saw — the template id and version the dialog sent — is no longer the\n// league's, so the dialog loads the current wording to read again.\nexport const WAIVER_SIGNING_REFUSAL_KEYS = ['waiverChanged'] as const;\nexport type WaiverSigningRefusal = (typeof WAIVER_SIGNING_REFUSAL_KEYS)[number];\n\n// Why a waiver-template publication was refused, named in its details so the editor answers it:\n// `templateVersionChanged` when the version the editor loaded is no longer the template's current\n// one, so the editor keeps the admin's draft and shows the newer wording before publishing again.\nexport const WAIVER_TEMPLATE_EDIT_REFUSAL_KEYS = ['templateVersionChanged'] as const;\nexport type WaiverTemplateEditRefusal = (typeof WAIVER_TEMPLATE_EDIT_REFUSAL_KEYS)[number];\n\n// The icon a team picks at creation; the persisted value is the icon component's name.\nexport const TEAM_ICON_KEYS = [\n 'Shield',\n 'Swords',\n 'Skull',\n 'Ghost',\n 'Cat',\n 'Dog',\n 'Bird',\n 'Fish',\n 'Rabbit',\n 'Snail',\n 'Turtle',\n 'Cherry',\n 'Apple',\n 'Grape',\n 'Rocket',\n 'Plane',\n 'Ship',\n 'Train',\n 'Car',\n 'Bike',\n 'Bolt',\n 'Star',\n 'Sun',\n 'Moon',\n 'Cloud',\n 'Crown',\n 'Diamond',\n 'Gem',\n 'Anchor',\n // Appended — the set only grows, and no stored key is ever renamed or removed. Seasonal and events.\n 'TreePine',\n 'Trees',\n 'TreeDeciduous',\n 'TreePalm',\n 'Snowflake',\n 'MountainSnow',\n 'Gift',\n 'PartyPopper',\n 'CandyCane',\n 'Candy',\n 'Lollipop',\n 'Cake',\n 'Egg',\n 'Clover',\n 'Heart',\n 'Flower',\n 'Flower2',\n 'Rose',\n 'Leaf',\n 'Sprout',\n 'Wheat',\n 'Sunrise',\n 'Rainbow',\n 'Bell',\n // Awards and sport.\n 'Trophy',\n 'Medal',\n 'Award',\n 'Ribbon',\n 'Flag',\n 'Target',\n 'Crosshair',\n 'Goal',\n 'Dumbbell',\n 'Footprints',\n // Power and the elements.\n 'Zap',\n 'Flame',\n 'FlameKindling',\n 'Bomb',\n 'Atom',\n 'Orbit',\n 'Sparkles',\n 'WandSparkles',\n 'Mountain',\n 'Tornado',\n 'Wind',\n 'Droplet',\n 'CloudLightning',\n 'MoonStar',\n // Arms and strongholds.\n 'Sword',\n 'Axe',\n 'Hammer',\n 'Pickaxe',\n 'ShieldHalf',\n 'Castle',\n // Animals.\n 'Squirrel',\n 'Rat',\n 'Panda',\n 'Shrimp',\n 'Worm',\n 'Bug',\n 'Shell',\n 'PawPrint',\n 'Feather',\n 'Bone',\n 'Origami',\n // Food.\n 'Citrus',\n 'Banana',\n 'Carrot',\n 'Pizza',\n 'Cookie',\n 'Donut',\n 'Coffee',\n // Games and music.\n 'Dices',\n 'Puzzle',\n 'Gamepad2',\n 'Spade',\n 'Club',\n 'Music',\n 'Guitar',\n 'Hexagon',\n 'Triangle',\n // Travel.\n 'Sailboat',\n 'Tractor',\n 'Truck',\n] as const;\nexport type TeamIcon = (typeof TEAM_ICON_KEYS)[number];\n\n// A picture's processed sizes, smallest first: every picture kind declares all three, and a display\n// asks for the smallest one that covers its slot.\nexport const PICTURE_VARIANT_KEYS = ['sm', 'md', 'lg'] as const;\nexport type PictureVariantKey = (typeof PICTURE_VARIANT_KEYS)[number];\n\n// What a stats check found, game tier first — a game's own numbers are the cause of the aggregate\n// findings, so Fix stats repairs games before it rebuilds what they feed.\nexport const GAME_TIER_DISCREPANCY_KIND_KEYS = [\n // A game whose document the check could not read: nothing else about it could be checked.\n 'gameUnreadable',\n 'invalidEvent',\n 'eventSequenceMismatch',\n // A game whose events do not hold exactly the sequences 1..n: a gap or a duplicate.\n 'eventSequenceGap',\n 'rollupMismatch',\n 'scoreMirrorMismatch',\n 'unrosteredStatLine',\n 'fantasyPointsStale',\n 'finalRecordMissing',\n 'finalRecordMismatch',\n 'participationSnapshotMismatch',\n 'gameHeld',\n] as const;\nexport const AGGREGATE_TIER_DISCREPANCY_KIND_KEYS = [\n 'aggregateMismatch',\n 'aggregateEntryStale',\n 'aggregateEntryMissing',\n 'hallOfFameLifetimeMismatch',\n] as const;\nexport const STATS_DISCREPANCY_KIND_KEYS = [\n ...GAME_TIER_DISCREPANCY_KIND_KEYS,\n ...AGGREGATE_TIER_DISCREPANCY_KIND_KEYS,\n] as const;\nexport type StatsDiscrepancyKind = (typeof STATS_DISCREPANCY_KIND_KEYS)[number];\n"]}
|
package/dist/types/uploads.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Why a picture's files are owed deletion (ARCH-102). A retirement is written in the same
|
|
1
|
+
// Why a picture's files are owed deletion (RULE-STD-ARCH-102). A retirement is written in the same
|
|
2
2
|
// transaction that drops a picture's last reference, fails its upload, or deletes its owner.
|
|
3
3
|
// removed an admin removed it from its gallery or its slot
|
|
4
4
|
// replaced a newer upload took its slot
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploads.js","sourceRoot":"","sources":["../../src/types/uploads.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"uploads.js","sourceRoot":"","sources":["../../src/types/uploads.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,6FAA6F;AAC7F,mEAAmE;AACnE,+CAA+C;AAC/C,8FAA8F;AAC9F,gFAAgF;AAChF,yEAAyE;AACzE,MAAM,CAAC,MAAM,8BAA8B,GAAG;IAC5C,SAAS;IACT,UAAU;IACV,YAAY;IACZ,cAAc;IACd,cAAc;CACN,CAAC","sourcesContent":["// Why a picture's files are owed deletion (RULE-STD-ARCH-102). A retirement is written in the same\n// transaction that drops a picture's last reference, fails its upload, or deletes its owner.\n// removed an admin removed it from its gallery or its slot\n// replaced a newer upload took its slot\n// superseded it finished after a newer upload already held the slot, so it never took it\n// uploadFailed its upload failed, and whatever sizes were written go with it\n// ownerDeleted its owner — a team, a location, an award — was deleted\nexport const PICTURE_RETIREMENT_REASON_KEYS = [\n 'removed',\n 'replaced',\n 'superseded',\n 'uploadFailed',\n 'ownerDeleted',\n] as const;\nexport type PictureRetirementReason = (typeof PICTURE_RETIREMENT_REASON_KEYS)[number];\n"]}
|