clone

a deno framework for local-first web apps that open instantly, work offline and sync when users choose

feat/fix-sync-enrollment-startup
lofi / package / runtime / mutation-taxonomy.ts
mutation-taxonomy.ts 1.6K
1/**2 * Package-owned mutation-error taxonomy.3 *4 * The sync node adjudicates a write that was accepted locally and emits a5 * rejection code. This module maps those codes onto the one distinction the6 * effect system acts on: permanent verdicts compensate, everything else stays7 * pending. The classification mirrors the taxonomy the lofi sync node8 * publishes; codes this package does not recognize are `unknown` and are9 * never treated as permanent, so an uninterpretable code can never trigger10 * compensation.11 *12 * @module13 */1415/**16 * How a rejection code is acted on: `permanent` verdicts settle the write as17 * `rejected` and run compensation, `transient` and `unknown` codes leave the18 * write pending until a later settlement attempt resolves it.19 */20export type MutationErrorClass = "permanent" | "transient" | "unknown";2122// The one permanent code the node emits today. Growing this set is a23// package-version decision made together with the node's taxonomy.24const permanentCodes = new Set(["permission_denied"]);2526// Codes describing delivery conditions rather than verdicts.27const transientCodes = new Set(["network", "timeout", "disconnected"]);2829/**30 * Classifies a sync-node rejection code. `permission_denied` is `permanent`;31 * known delivery-condition codes are `transient`; anything else — including a32 * missing code — is `unknown`. Compensation gates on `permanent` only.33 */34export function classifyMutationError(code: string | null | undefined): MutationErrorClass {35 if (!code) return "unknown";36 if (permanentCodes.has(code)) return "permanent";37 if (transientCodes.has(code)) return "transient";38 return "unknown";39}