From 03fa4478643e9fc61beb45d8945a568af2cf0611 Mon Sep 17 00:00:00 2001 From: zetaloop Date: Sun, 22 Feb 2026 14:50:54 +0800 Subject: [PATCH] refactor(policy): add centralized decision helpers --- lib/policy/actor.ts | 7 +++++++ lib/policy/assert.ts | 18 ++++++++++++++++++ lib/policy/decision.ts | 17 +++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 lib/policy/actor.ts create mode 100644 lib/policy/assert.ts create mode 100644 lib/policy/decision.ts diff --git a/lib/policy/actor.ts b/lib/policy/actor.ts new file mode 100644 index 0000000..9e97b9b --- /dev/null +++ b/lib/policy/actor.ts @@ -0,0 +1,7 @@ +import type { UserRole } from "@/lib/types" + +export interface Actor { + userId: string + role: UserRole + shopId?: string +} diff --git a/lib/policy/assert.ts b/lib/policy/assert.ts new file mode 100644 index 0000000..cbab0e1 --- /dev/null +++ b/lib/policy/assert.ts @@ -0,0 +1,18 @@ +import type { Actor } from "@/lib/policy/actor" +import type { PolicyDecision, ReasonCode } from "@/lib/policy/decision" + +export function allow(): PolicyDecision { + return { ok: true } +} + +export function deny(reasonCode: ReasonCode, message?: string): PolicyDecision { + return { ok: false, reasonCode, message } +} + +export function requireAuth(actor: Actor | null | undefined): PolicyDecision { + if (!actor?.userId) { + return deny("AUTH_REQUIRED", "请先登录") + } + + return allow() +} diff --git a/lib/policy/decision.ts b/lib/policy/decision.ts new file mode 100644 index 0000000..5b55296 --- /dev/null +++ b/lib/policy/decision.ts @@ -0,0 +1,17 @@ +export type ReasonCode = + | "AUTH_REQUIRED" + | "NOT_FOUND" + | "NOT_PARTICIPANT" + | "ROLE_FORBIDDEN" + | "INVALID_STATUS" + | "ALREADY_DONE" + | "DISPUTE_LOCKED" + | "PAYMENT_FAILED" + | "IDEMPOTENT_NOOP" + | "VALIDATION_FAILED" + +export interface PolicyDecision { + ok: boolean + reasonCode?: ReasonCode + message?: string +}