qumra-pos-auth 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/crypto/base64.ts","../src/crypto/NoblePinHasher.ts","../src/crypto/NobleSignatureVerifier.ts","../src/errors.ts","../src/time.ts","../src/token/TokenManager.ts","../src/pin/PinManager.ts","../src/activation/ActivationManager.ts","../src/policy.ts","../src/service/AuthService.ts","../src/createAuth.ts"],"names":["randomBytes","argon2idAsync","utf8ToBytes","ed25519"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Base64 محمول (standard + url-safe) بدون الاعتماد على Buffer أو btoa — علشان نفس\n * الكود يشتغل في Node و المتصفح و React Native. الترميز بدون padding افتراضياً\n * (صيغة PHC و JWT كده)، وفك الترميز بيتقبّل بوجود أو غياب الـ padding.\n */\nconst STD = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\nconst URL = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n\nfunction encode(bytes: Uint8Array, alphabet: string): string {\n let out = \"\";\n for (let i = 0; i < bytes.length; i += 3) {\n const b0 = bytes[i]!;\n const b1 = i + 1 < bytes.length ? bytes[i + 1]! : 0;\n const b2 = i + 2 < bytes.length ? bytes[i + 2]! : 0;\n const triple = (b0 << 16) | (b1 << 8) | b2;\n out += alphabet[(triple >> 18) & 63];\n out += alphabet[(triple >> 12) & 63];\n if (i + 1 < bytes.length) out += alphabet[(triple >> 6) & 63];\n if (i + 2 < bytes.length) out += alphabet[triple & 63];\n }\n return out;\n}\n\nfunction decode(str: string, alphabet: string): Uint8Array {\n const lookup = new Int16Array(128).fill(-1);\n for (let i = 0; i < alphabet.length; i++) lookup[alphabet.charCodeAt(i)] = i;\n // شيل الـ padding والمسافات\n const clean = str.replace(/[=\\s]/g, \"\");\n const out = new Uint8Array(Math.floor((clean.length * 6) / 8));\n let bits = 0;\n let value = 0;\n let o = 0;\n for (let i = 0; i < clean.length; i++) {\n const c = clean.charCodeAt(i);\n const idx = c < 128 ? lookup[c]! : -1;\n if (idx < 0) throw new Error(\"base64: حرف غير صالح\");\n value = (value << 6) | idx;\n bits += 6;\n if (bits >= 8) {\n bits -= 8;\n out[o++] = (value >> bits) & 0xff;\n }\n }\n return out;\n}\n\nexport const b64 = {\n encode: (b: Uint8Array): string => encode(b, STD),\n decode: (s: string): Uint8Array => decode(s, STD),\n};\n\nexport const b64url = {\n encode: (b: Uint8Array): string => encode(b, URL),\n decode: (s: string): Uint8Array => decode(s, URL),\n};\n","import { argon2idAsync } from \"@noble/hashes/argon2\";\nimport { randomBytes, utf8ToBytes } from \"@noble/hashes/utils\";\nimport type { PinHasher } from \"../ports/PinHasher\";\nimport { b64 } from \"./base64\";\n\n/**\n * الافتراضي لتعمية الـ PIN: argon2id بصيغة PHC القياسية، pure JS من @noble/hashes.\n * نفس الصيغة اللي السيرفر بينتجها فالـ hash المتزامن يتحقق محلياً (نفس الكود\n * أونلاين وأوفلاين).\n *\n * صيغة الناتج: $argon2id$v=19$m=<m>,t=<t>,p=<p>$<saltB64>$<hashB64>\n */\nexport interface Argon2Params {\n /** iterations (t). */\n t: number;\n /** memory بالـ KiB (m). */\n m: number;\n /** parallelism (p). */\n p: number;\n /** طول الـ hash بالبايت. */\n dkLen: number;\n}\n\n/** إعداد متزن للأجهزة (64MiB, 3 مرات) — يطابق الافتراضي الشائع للسيرفر. */\nexport const DEFAULT_ARGON2_PARAMS: Argon2Params = {\n t: 3,\n m: 64 * 1024,\n p: 1,\n dkLen: 32,\n};\n\nconst V = 19; // argon2 version 1.3\n\nfunction constantTimeEqual(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false;\n let diff = 0;\n for (let i = 0; i < a.length; i++) diff |= a[i]! ^ b[i]!;\n return diff === 0;\n}\n\nexport class NoblePinHasher implements PinHasher {\n private readonly params: Argon2Params;\n\n constructor(params: Argon2Params = DEFAULT_ARGON2_PARAMS) {\n this.params = params;\n }\n\n async hash(pin: string): Promise<string> {\n const salt = randomBytes(16);\n const { t, m, p, dkLen } = this.params;\n const out = await argon2idAsync(utf8ToBytes(pin), salt, { t, m, p, dkLen });\n return `$argon2id$v=${V}$m=${m},t=${t},p=${p}$${b64.encode(salt)}$${b64.encode(out)}`;\n }\n\n async verify(pin: string, encoded: string): Promise<boolean> {\n const parsed = parsePhc(encoded);\n if (!parsed) return false;\n const out = await argon2idAsync(utf8ToBytes(pin), parsed.salt, {\n t: parsed.t,\n m: parsed.m,\n p: parsed.p,\n dkLen: parsed.hash.length,\n });\n return constantTimeEqual(out, parsed.hash);\n }\n}\n\ninterface Phc {\n m: number;\n t: number;\n p: number;\n salt: Uint8Array;\n hash: Uint8Array;\n}\n\n/** يفكّ صيغة PHC لـ argon2id. بيرجّع null لو مش متعرّف عليها (نتيجتها verify=false). */\nfunction parsePhc(encoded: string): Phc | null {\n // $argon2id$v=19$m=..,t=..,p=..$salt$hash\n const parts = encoded.split(\"$\");\n // [\"\", \"argon2id\", \"v=19\", \"m=..,t=..,p=..\", \"<salt>\", \"<hash>\"]\n if (parts.length !== 6) return null;\n if (parts[1] !== \"argon2id\") return null;\n const paramStr = parts[3];\n const saltStr = parts[4];\n const hashStr = parts[5];\n if (paramStr === undefined || saltStr === undefined || hashStr === undefined) {\n return null;\n }\n const params = new Map<string, number>();\n for (const kv of paramStr.split(\",\")) {\n const [k, v] = kv.split(\"=\");\n if (k === undefined || v === undefined) return null;\n const n = Number(v);\n if (!Number.isFinite(n)) return null;\n params.set(k, n);\n }\n const m = params.get(\"m\");\n const t = params.get(\"t\");\n const p = params.get(\"p\");\n if (m === undefined || t === undefined || p === undefined) return null;\n try {\n return { m, t, p, salt: b64.decode(saltStr), hash: b64.decode(hashStr) };\n } catch {\n return null;\n }\n}\n","import { ed25519 } from \"@noble/curves/ed25519\";\nimport type { SignatureVerifier } from \"../ports/SignatureVerifier\";\n\n/**\n * الافتراضي للتحقق من التوقيع: Ed25519 من @noble/curves (pure JS). بيتحقق محلياً\n * من مفاتيح التفعيل الموقّعة بمفتاح قمرة الخاص — بدون أي نداء سيرفر.\n */\nexport class NobleSignatureVerifier implements SignatureVerifier {\n async verify(\n message: Uint8Array,\n signature: Uint8Array,\n publicKey: Uint8Array,\n ): Promise<boolean> {\n try {\n return ed25519.verify(signature, message, publicKey);\n } catch {\n // توقيع/مفتاح بحجم غلط → اعتبره غير صالح بدل ما نرمي.\n return false;\n }\n }\n}\n","/**\n * فرق جوهري بين نوعي الفشل — بيحدد سلوك الـ auth بالكامل:\n *\n * - AuthNetworkError: النت/السيرفر مش متاح (offline أو 5xx). قابل لإعادة المحاولة،\n * ومابيمسحش أي توكن. النتيجة: sync يقف مؤقتاً (pause) والجلسة تفضل شغّالة أوفلاين.\n *\n * - AuthRejectedError: السيرفر رفض صراحةً (401/400 invalid_grant، refresh متبطّل،\n * كلمة سر غلط). دائم — إعادة المحاولة مش هتفيد. النتيجة: التوكنات تتمسح والجلسة\n * تتحوّل للوضع الأوفلاين/المقفول. البيانات التجارية لا تُمسح أبداً.\n */\nexport class AuthNetworkError extends Error {\n constructor(message: string, cause?: unknown) {\n super(message, { cause });\n this.name = \"AuthNetworkError\";\n }\n}\n\nexport class AuthRejectedError extends Error {\n /** كود السيرفر لو متاح (invalid_grant, invalid_credentials …). */\n readonly code: string | undefined;\n constructor(message: string, code?: string, cause?: unknown) {\n super(message, { cause });\n this.name = \"AuthRejectedError\";\n this.code = code;\n }\n}\n","/**\n * كل حسابات الوقت في الـ auth بالمللي ثانية منذ epoch (نفس شكل Date.now).\n * دالة now محقونة علشان الاختبارات تتحكم في الزمن (زي SyncEngine).\n */\nexport type Clock = () => number;\n\nexport const systemClock: Clock = () => Date.now();\n\nexport const SECOND = 1000;\nexport const MINUTE = 60 * SECOND;\nexport const HOUR = 60 * MINUTE;\nexport const DAY = 24 * HOUR;\n","import type { AuthApi } from \"../ports/AuthApi\";\nimport type { AuthVault } from \"../ports/AuthVault\";\nimport { AuthNetworkError, AuthRejectedError } from \"../errors\";\nimport type { Clock } from \"../time\";\nimport { systemClock, SECOND } from \"../time\";\nimport type { AuthTokens, LoginInput, TokenResponse } from \"../types\";\n\n/**\n * نتيجة محاولة ضمان توكن صالح. غنية علشان AuthService يقدر يفرّق بين \"النت مقطوع\"\n * (pause، الجلسة تكمل) و \"السيرفر رفض\" (التوكنات اتمسحت، ندخل مسار grace/lock).\n */\nexport type RefreshOutcome =\n | { status: \"valid\"; tokens: AuthTokens } // access لسه صالح، مفيش داعي لـ refresh\n | { status: \"refreshed\"; tokens: AuthTokens } // عملنا refresh بنجاح\n | { status: \"network\" } // offline/5xx — التوكنات محفوظة، sync يقف\n | { status: \"rejected\" } // refresh متبطّل — التوكنات اتمسحت\n | { status: \"signed-out\" }; // مفيش توكنات أصلاً\n\nexport interface TokenManagerOptions {\n vault: AuthVault;\n api: AuthApi;\n now?: Clock;\n /**\n * هامش أمان: نعتبر التوكن \"منتهي\" قبل انتهائه الحقيقي بـ skew — علشان ماننفّذش\n * نداء بتوكن هيقع أثناء الرحلة. افتراضي 30 ثانية.\n */\n skewMs?: number;\n /** يتنادى بعد كل اتصال ناجح بالسيرفر (login/refresh) — AuthService بيحدّث الـ meta. */\n onServerContact?: (at: number) => void | Promise<void>;\n}\n\n/**\n * TokenVault + OAuth. بيملك دورة حياة التوكنات: login، refresh دوّار single-flight،\n * وينتج التوكن الصالح للـ SyncEngine. القاعدة الذهبية: getValidToken مابيرميش أبداً —\n * null معناها \"اعمل pause\"، مش استثناء.\n */\nexport class TokenManager {\n private readonly vault: AuthVault;\n private readonly api: AuthApi;\n private readonly now: Clock;\n private readonly skewMs: number;\n private readonly onServerContact:\n | ((at: number) => void | Promise<void>)\n | undefined;\n\n /** single-flight: كل النداءات المتزامنة بتشارك نفس عملية الـ refresh. */\n private inflight: Promise<RefreshOutcome> | null = null;\n\n /**\n * نسخة في الذاكرة من آخر توكنات معروفة. الغرض الوحيد: peekValidToken المتزامن\n * — لأن SyncEngine.getAuthToken متزامن بينما الـ vault async. بتتحدّث مع كل\n * تحميل/حفظ للتوكنات، ودورة الـ refresh الخلفية بتحافظ عليها دافية.\n */\n private cached: AuthTokens | null = null;\n\n constructor(opts: TokenManagerOptions) {\n this.vault = opts.vault;\n this.api = opts.api;\n this.now = opts.now ?? systemClock;\n this.skewMs = opts.skewMs ?? 30 * SECOND;\n this.onServerContact = opts.onServerContact;\n }\n\n /** تسجيل دخول أونلاين. بيرمي AuthRejectedError/AuthNetworkError زي الـ api. */\n async login(input: LoginInput): Promise<AuthTokens> {\n const resp = await this.api.login(input);\n const tokens = this.toTokens(resp);\n await this.vault.saveTokens(tokens);\n this.cached = tokens;\n await this.onServerContact?.(this.now());\n return tokens;\n }\n\n /** خروج: إبطال best-effort على السيرفر ثم مسح التوكنات المحلية. */\n async logout(): Promise<void> {\n const tokens = await this.vault.loadTokens();\n if (tokens && this.api.revoke) {\n try {\n await this.api.revoke(tokens.refreshToken);\n } catch {\n // الإبطال best-effort — لو النت مقطوع نمسح محلياً برضه.\n }\n }\n await this.vault.saveTokens(null);\n this.cached = null;\n }\n\n async getTokens(): Promise<AuthTokens | null> {\n const tokens = await this.vault.loadTokens();\n this.cached = tokens;\n return tokens;\n }\n\n /** يملأ الكاش من الـ vault مرة (عند الإقلاع) — علشان peek يشتغل قبل أي نداء. */\n async primeCache(): Promise<void> {\n this.cached = await this.vault.loadTokens();\n }\n\n /**\n * توكن access صالح متزامن من الكاش — من غير أي I/O أو refresh. ده اللي بيتوصّل\n * لـ SyncEngine.getAuthToken. بيرجّع null لو مفيش كاش أو الكاش منتهي؛ دورة الـ\n * refresh الخلفية (getValidToken) هي اللي بتجدّد الكاش.\n */\n peekValidToken(): string | null {\n if (!this.cached) return null;\n return this.isAccessValid(this.cached) ? this.cached.accessToken : null;\n }\n\n /**\n * التوكن الصالح للـ SyncEngine. مابيرميش: أي فشل → null (= pause).\n */\n async getValidToken(): Promise<string | null> {\n const outcome = await this.ensureFresh();\n switch (outcome.status) {\n case \"valid\":\n case \"refreshed\":\n return outcome.tokens.accessToken;\n default:\n return null;\n }\n }\n\n /**\n * يضمن توكن access صالح: يرجّعه لو صالح، أو يعمل refresh دوّار single-flight.\n * مابيرميش — بيرجّع RefreshOutcome. AuthService بيستخدمه لتحديث حالة الوصول.\n */\n async ensureFresh(): Promise<RefreshOutcome> {\n const tokens = await this.vault.loadTokens();\n this.cached = tokens;\n if (!tokens) return { status: \"signed-out\" };\n if (this.isAccessValid(tokens)) return { status: \"valid\", tokens };\n // الـ access انتهى. من غير refresh صالح مانقدرش نجدّد أوفلاين → pause.\n if (!this.isRefreshValid(tokens)) return { status: \"network\" };\n return this.refreshOnce();\n }\n\n isAccessValid(tokens: AuthTokens): boolean {\n return this.now() < tokens.accessExpiresAt - this.skewMs;\n }\n\n isRefreshValid(tokens: AuthTokens): boolean {\n return this.now() < tokens.refreshExpiresAt;\n }\n\n /** refresh single-flight: نداء واحد بس بيطير حتى لو اتنادى من كذا مكان. */\n private refreshOnce(): Promise<RefreshOutcome> {\n if (this.inflight) return this.inflight;\n this.inflight = this.doRefresh().finally(() => {\n this.inflight = null;\n });\n return this.inflight;\n }\n\n private async doRefresh(): Promise<RefreshOutcome> {\n const current = await this.vault.loadTokens();\n if (!current) return { status: \"signed-out\" };\n // ممكن نداء تاني كان سبقنا وجدّد بالفعل وإحنا بنستنى — اتأكد.\n if (this.isAccessValid(current)) return { status: \"valid\", tokens: current };\n try {\n const resp = await this.api.refresh(current.refreshToken);\n const next = this.toTokens(resp);\n await this.vault.saveTokens(next); // refresh دوّار: بنخزّن الـ refresh الجديد\n this.cached = next;\n await this.onServerContact?.(this.now());\n return { status: \"refreshed\", tokens: next };\n } catch (err) {\n if (err instanceof AuthRejectedError) {\n // الـ refresh اتبطّل/اتسحب → امسح التوكنات (مش البيانات). ندخل offline/lock.\n await this.vault.saveTokens(null);\n this.cached = null;\n return { status: \"rejected\" };\n }\n if (err instanceof AuthNetworkError) {\n // النت مقطوع → احتفظ بالتوكنات، جرّب تاني الدورة الجاية.\n return { status: \"network\" };\n }\n // خطأ غير متوقع — عامله معاملة الشبكة (محافِظ، مايمسحش).\n return { status: \"network\" };\n }\n }\n\n private toTokens(resp: TokenResponse): AuthTokens {\n const at = this.now();\n return {\n accessToken: resp.accessToken,\n refreshToken: resp.refreshToken,\n accessExpiresAt: at + resp.expiresInSec * SECOND,\n refreshExpiresAt: at + resp.refreshExpiresInSec * SECOND,\n tokenType: resp.tokenType ?? \"Bearer\",\n };\n }\n}\n","import type { CashierDirectory } from \"../ports/CashierDirectory\";\nimport type { PinHasher } from \"../ports/PinHasher\";\nimport type { Clock } from \"../time\";\nimport { systemClock, MINUTE } from \"../time\";\nimport type { CashierRecord, PinResult, PublicCashier } from \"../types\";\n\nexport interface PinManagerOptions {\n directory: CashierDirectory;\n hasher: PinHasher;\n now?: Clock;\n /** عدد المحاولات الخاطئة قبل القفل المؤقت. افتراضي 5. */\n maxAttempts?: number;\n /** مدة القفل بعد استنفاد المحاولات. افتراضي دقيقة. */\n lockoutMs?: number;\n}\n\ninterface AttemptState {\n count: number;\n lockedUntil: number;\n}\n\n/**\n * دخول الكاشير اليومي بالـ PIN المحلي. بيتحقق بـ argon2id ضد الـ hash المتزامن —\n * نفس الكود أونلاين وأوفلاين، مفيش نداء سيرفر. فيه قفل مؤقت لكل كاشير بعد محاولات\n * فاشلة متتالية (حماية من التخمين).\n *\n * ملاحظة: PinManager بيتحقق بس — إدارة الكاشيرية (إضافة/تعديل PIN) من داشبورد\n * التاجر، وبتوصل الجهاز عن طريق مزامنة جدول cashiers.\n */\nexport class PinManager {\n private readonly directory: CashierDirectory;\n private readonly hasher: PinHasher;\n private readonly now: Clock;\n private readonly maxAttempts: number;\n private readonly lockoutMs: number;\n private readonly attempts = new Map<string, AttemptState>();\n\n constructor(opts: PinManagerOptions) {\n this.directory = opts.directory;\n this.hasher = opts.hasher;\n this.now = opts.now ?? systemClock;\n this.maxAttempts = opts.maxAttempts ?? 5;\n this.lockoutMs = opts.lockoutMs ?? MINUTE;\n }\n\n /** قائمة الكاشيرية للعرض (من غير الـ hashes). */\n async listCashiers(): Promise<PublicCashier[]> {\n const rows = await this.directory.listCashiers();\n return rows.map((c) => ({ id: c.id, name: c.name, active: c.active }));\n }\n\n /**\n * يتحقق من PIN كاشير معيّن. النجاح بيصفّر عدّاد محاولاته؛ الفشل بيزوّده ويقفل\n * مؤقتاً عند الوصول للحد.\n */\n async verify(cashierId: string, pin: string): Promise<PinResult> {\n const now = this.now();\n const state = this.attempts.get(cashierId);\n if (state && state.lockedUntil > now) {\n return {\n ok: false,\n reason: \"locked\",\n retryAfterMs: state.lockedUntil - now,\n };\n }\n\n const cashier = await this.findCashier(cashierId);\n if (!cashier) return { ok: false, reason: \"unknown-cashier\" };\n if (!cashier.active) return { ok: false, reason: \"inactive\" };\n\n const valid = await this.hasher.verify(pin, cashier.pinHash);\n if (valid) {\n this.attempts.delete(cashierId);\n return {\n ok: true,\n cashier: { cashierId: cashier.id, name: cashier.name, since: now },\n };\n }\n\n return this.registerFailure(cashierId, now);\n }\n\n /** يفكّ القفل يدوياً (مثلاً المدير سمح). */\n reset(cashierId: string): void {\n this.attempts.delete(cashierId);\n }\n\n private registerFailure(cashierId: string, now: number): PinResult {\n const prev = this.attempts.get(cashierId);\n const count = (prev?.count ?? 0) + 1;\n if (count >= this.maxAttempts) {\n const lockedUntil = now + this.lockoutMs;\n this.attempts.set(cashierId, { count: 0, lockedUntil });\n return { ok: false, reason: \"locked\", retryAfterMs: this.lockoutMs };\n }\n this.attempts.set(cashierId, { count, lockedUntil: 0 });\n return {\n ok: false,\n reason: \"bad-pin\",\n attemptsLeft: this.maxAttempts - count,\n };\n }\n\n private async findCashier(id: string): Promise<CashierRecord | undefined> {\n const rows = await this.directory.listCashiers();\n return rows.find((c) => c.id === id);\n }\n}\n","import type { AuthVault } from \"../ports/AuthVault\";\nimport type { SignatureVerifier } from \"../ports/SignatureVerifier\";\nimport { b64url } from \"../crypto/base64\";\nimport type { Clock } from \"../time\";\nimport { systemClock } from \"../time\";\nimport type {\n ActivationClaims,\n ActivationResult,\n StoredActivation,\n} from \"../types\";\n\n/**\n * التفعيل الأوفلاين: مفتاح موقّع بـ Ed25519 يصدره سيرفر قمرة، يتحقق منه الجهاز\n * محلياً بالمفتاح العام المثبّت — بدون أي اتصال بالسيرفر. ده اللي بيسمح بوضع\n * offline-activated لجهاز اتفعّل من غير ما يشوف النت.\n *\n * صيغة المفتاح (زي JWT بس Ed25519): <payloadB64url>.<signatureB64url>\n * التوقيع على بايتات مقطع الـ payload نفسه (نص b64url).\n */\nexport interface ActivationManagerOptions {\n vault: AuthVault;\n verifier: SignatureVerifier;\n /** المفتاح العام لقمرة (32 بايت Ed25519) — مثبّت في التطبيق. */\n publicKey: Uint8Array;\n now?: Clock;\n \n /** لو محدَّد، لازم claims.deviceId يطابقه (منع نقل المفتاح لجهاز تاني). */\n deviceId?: string;\n}\n\nexport class ActivationManager {\n private readonly vault: AuthVault;\n private readonly verifier: SignatureVerifier;\n private readonly publicKey: Uint8Array;\n private readonly now: Clock;\n private readonly deviceId: string | undefined;\n\n constructor(opts: ActivationManagerOptions) {\n this.vault = opts.vault;\n this.verifier = opts.verifier;\n this.publicKey = opts.publicKey;\n this.now = opts.now ?? systemClock;\n this.deviceId = opts.deviceId;\n }\n\n /**\n * يتحقق من مفتاح تفعيل ويخزّنه لو صالح. الترتيب: صيغة → توقيع → الجهاز → الانتهاء.\n * التوقيع بيتفحص قبل أي حاجة تانية علشان مانثقش في أي claim قبل التأكد إنه من قمرة.\n */\n async activate(activationKey: string): Promise<ActivationResult> {\n const parsed = this.parse(activationKey);\n if (!parsed) return { ok: false, reason: \"malformed\" };\n\n const okSig = await this.verifier.verify(\n parsed.signedBytes,\n parsed.signature,\n this.publicKey,\n );\n if (!okSig) return { ok: false, reason: \"bad-signature\" };\n\n const claims = parsed.claims;\n if (this.deviceId !== undefined && claims.deviceId !== this.deviceId) {\n return { ok: false, reason: \"wrong-device\" };\n }\n\n const now = this.now();\n const graceMs = claims.graceMs ?? 0;\n if (now >= claims.expiresAt + graceMs) {\n return { ok: false, reason: \"expired\" };\n }\n\n const stored: StoredActivation = {\n claims,\n key: activationKey,\n verifiedAt: now,\n };\n await this.vault.saveActivation(stored);\n return { ok: true, claims };\n }\n\n async getActivation(): Promise<StoredActivation | null> {\n return this.vault.loadActivation();\n }\n\n /**\n * يعيد التحقق من المفتاح المخزّن (توقيع + جهاز) ويحدّث verifiedAt. بيُستدعى عند\n * الإقلاع علشان نتأكد إن المفتاح المخزّن لسه سليم ومش متلاعب فيه.\n */\n async revalidateStored(): Promise<ActivationResult | null> {\n const stored = await this.vault.loadActivation();\n if (!stored) return null;\n return this.activate(stored.key);\n }\n\n async clear(): Promise<void> {\n await this.vault.saveActivation(null);\n }\n\n private parse(\n key: string,\n ):\n | { claims: ActivationClaims; signedBytes: Uint8Array; signature: Uint8Array }\n | null {\n const dot = key.indexOf(\".\");\n if (dot <= 0 || dot === key.length - 1) return null;\n const payloadB64 = key.slice(0, dot);\n const sigB64 = key.slice(dot + 1);\n let claims: ActivationClaims;\n let signature: Uint8Array;\n try {\n const json = new TextDecoder().decode(b64url.decode(payloadB64));\n claims = JSON.parse(json) as ActivationClaims;\n signature = b64url.decode(sigB64);\n } catch {\n return null;\n }\n if (!isValidClaims(claims)) return null;\n // التوقيع على بايتات مقطع الـ payload (نص b64url) — زي ما وقّعه السيرفر.\n const signedBytes = new TextEncoder().encode(payloadB64);\n return { claims, signedBytes, signature };\n }\n}\n\nfunction isValidClaims(c: unknown): c is ActivationClaims {\n if (typeof c !== \"object\" || c === null) return false;\n const o = c as Record<string, unknown>;\n return (\n typeof o.merchantId === \"string\" &&\n typeof o.deviceId === \"string\" &&\n typeof o.issuedAt === \"number\" &&\n typeof o.expiresAt === \"number\"\n );\n}\n","import type { AccessPolicy } from \"./types\";\nimport { DAY } from \"./time\";\n\n/**\n * الافتراضي: 30 يوم أوفلاين مسموحة (يطابق عمر الـ refresh)، بعدها 3 أيام grace\n * (تحذير للمدير) ثم قفل البيع الجديد. البيانات لا تُمسح أبداً في أي مرحلة.\n */\nexport const DEFAULT_ACCESS_POLICY: AccessPolicy = {\n maxOfflineMs: 30 * DAY,\n graceMs: 3 * DAY,\n};\n","import type { AuthVault } from \"../ports/AuthVault\";\nimport type { TokenManager } from \"../token/TokenManager\";\nimport type { PinManager } from \"../pin/PinManager\";\nimport type { ActivationManager } from \"../activation/ActivationManager\";\nimport type { Clock } from \"../time\";\nimport { systemClock } from \"../time\";\nimport { DEFAULT_ACCESS_POLICY } from \"../policy\";\nimport type {\n AccessPolicy,\n AccessState,\n ActivationResult,\n AuthMeta,\n AuthStatus,\n LoginInput,\n OperatingMode,\n PinResult,\n PublicCashier,\n StoredActivation,\n} from \"../types\";\n\nexport interface AuthServiceOptions {\n vault: AuthVault;\n tokenManager: TokenManager;\n pinManager: PinManager;\n activationManager: ActivationManager;\n policy?: AccessPolicy;\n now?: Clock;\n}\n\ntype Listener = (status: AuthStatus) => void;\n\nconst EMPTY_META: AuthMeta = {\n lastServerContactAt: null,\n activatedOnlineAt: null,\n};\n\n/**\n * الواجهة الموحّدة للـ auth. بتجمع الثلاث مدراء وبتدير آلة الحالة\n * (active → grace → locked) والأوضاع الثلاثة. بتعرض callback واحد getValidToken\n * للـ SyncEngine، وبثّ حالة onStatusChange للـ UI.\n *\n * مبدأ ثابت: مفيش أي مسار هنا بيمسح بيانات تجارية — أسوأ حالة إن البيع الجديد\n * يتقفل. مسح التوكنات (عند رفض السيرفر) مش مسح للـ outbox أو التاريخ.\n */\nexport class AuthService {\n private readonly vault: AuthVault;\n private readonly now: Clock;\n private readonly policy: AccessPolicy;\n readonly tokens: TokenManager;\n readonly pins: PinManager;\n readonly activation: ActivationManager;\n\n private readonly listeners = new Set<Listener>();\n private status: AuthStatus = {\n mode: \"unactivated\",\n access: \"locked\",\n tokenValid: false,\n cashier: null,\n graceEndsAt: null,\n lockedReason: LOCK_REASON_UNACTIVATED,\n lastServerContactAt: null,\n activation: null,\n };\n\n constructor(opts: AuthServiceOptions) {\n this.vault = opts.vault;\n this.tokens = opts.tokenManager;\n this.pins = opts.pinManager;\n this.activation = opts.activationManager;\n this.policy = opts.policy ?? DEFAULT_ACCESS_POLICY;\n this.now = opts.now ?? systemClock;\n }\n\n // -------------------------------------------------------------------------\n // إقلاع + إعادة تقييم\n // -------------------------------------------------------------------------\n\n /** الإقلاع: يملأ كاش التوكن، يعيد التحقق من مفتاح التفعيل المخزّن، ثم يحسب الحالة. */\n async init(): Promise<AuthStatus> {\n await this.tokens.primeCache();\n const check = await this.activation.revalidateStored();\n if (check && !check.ok && (check.reason === \"bad-signature\" || check.reason === \"wrong-device\")) {\n // مفتاح متلاعب فيه أو منقول لجهاز تاني → ماينفعش نثق فيه.\n await this.activation.clear();\n }\n return this.reevaluate();\n }\n\n /**\n * يحاول تحديث التوكن (لو النت رجع) ثم يعيد حساب الحالة. التطبيق بينادي ده دورياً\n * وبعد أي reconnect. مابيرميش.\n */\n async refresh(): Promise<AuthStatus> {\n await this.tokens.ensureFresh();\n return this.reevaluate();\n }\n\n getStatus(): AuthStatus {\n return this.status;\n }\n\n /** هل مسموح ببيع جديد دلوقتي؟ (locked = لأ). */\n canSell(): boolean {\n return this.status.access !== \"locked\";\n }\n\n onStatusChange(cb: Listener): () => void {\n this.listeners.add(cb);\n cb(this.status);\n return () => this.listeners.delete(cb);\n }\n\n // -------------------------------------------------------------------------\n // الجهاز/التاجر\n // -------------------------------------------------------------------------\n\n /** تسجيل دخول أونلاين. بيرمي زي الـ api (rejected/network). */\n async onlineLogin(input: LoginInput): Promise<AuthStatus> {\n await this.tokens.login(input); // بيحدّث الـ meta عبر onServerContact\n return this.reevaluate();\n }\n\n /** إدخال مفتاح تفعيل أوفلاين. */\n async activateOffline(activationKey: string): Promise<ActivationResult> {\n const result = await this.activation.activate(activationKey);\n await this.reevaluate();\n return result;\n }\n\n /** خروج التاجر: يمسح التوكنات وجلسة الكاشير (مش البيانات، مش التفعيل). */\n async logout(): Promise<AuthStatus> {\n await this.tokens.logout();\n await this.vault.saveSession(null);\n return this.reevaluate();\n }\n\n /** callback الوحيد للـ SyncEngine (async). null = pause. */\n getValidToken(): Promise<string | null> {\n return this.tokens.getValidToken();\n }\n\n /**\n * نسخة متزامنة للـ SyncEngine (getAuthToken بتاعه متزامن). بترجّع آخر توكن صالح\n * من الكاش من غير I/O؛ refresh()/getValidToken الدورية هي اللي بتدفّي الكاش.\n */\n getAccessTokenSync(): string | null {\n return this.tokens.peekValidToken();\n }\n\n /** يُمرَّر للـ TokenManager: يسجّل آخر اتصال ناجح بالسيرفر ويعلّم التفعيل الأونلاين. */\n async recordServerContact(at: number): Promise<void> {\n const meta = (await this.vault.loadMeta()) ?? EMPTY_META;\n await this.vault.saveMeta({\n lastServerContactAt: at,\n activatedOnlineAt: meta.activatedOnlineAt ?? at,\n });\n }\n\n // -------------------------------------------------------------------------\n // الكاشير (PIN)\n // -------------------------------------------------------------------------\n\n async listCashiers(): Promise<PublicCashier[]> {\n return this.pins.listCashiers();\n }\n\n async cashierLogin(cashierId: string, pin: string): Promise<PinResult> {\n const result = await this.pins.verify(cashierId, pin);\n if (result.ok) {\n await this.vault.saveSession(result.cashier);\n await this.reevaluate();\n }\n return result;\n }\n\n async cashierLogout(): Promise<void> {\n await this.vault.saveSession(null);\n await this.reevaluate();\n }\n\n // -------------------------------------------------------------------------\n // حساب الحالة\n // -------------------------------------------------------------------------\n\n private async reevaluate(): Promise<AuthStatus> {\n const next = await this.computeStatus();\n const changed = JSON.stringify(next) !== JSON.stringify(this.status);\n this.status = next;\n if (changed) {\n for (const cb of this.listeners) cb(next);\n }\n return next;\n }\n\n private async computeStatus(): Promise<AuthStatus> {\n const [tokens, session, activation, metaRaw] = await Promise.all([\n this.vault.loadTokens(),\n this.vault.loadSession(),\n this.vault.loadActivation(),\n this.vault.loadMeta(),\n ]);\n const meta = metaRaw ?? EMPTY_META;\n const now = this.now();\n\n const tokenValid = tokens ? this.tokens.isAccessValid(tokens) : false;\n const mode = deriveMode(tokenValid, meta, activation);\n const access = computeAccess(mode, now, meta, activation, this.policy);\n\n return {\n mode,\n access: access.state,\n tokenValid,\n cashier: session,\n graceEndsAt: access.graceEndsAt,\n lockedReason: access.lockedReason,\n lastServerContactAt: meta.lastServerContactAt,\n activation,\n };\n }\n}\n\nconst LOCK_REASON_UNACTIVATED =\n \"الجهاز غير مفعّل — سجّل الدخول أونلاين أو أدخل مفتاح تفعيل\";\nconst LOCK_REASON_OFFLINE_TOO_LONG =\n \"الجهاز أوفلاين من مدة طويلة — لازم يتصل بالسيرفر لتجديد الجلسة\";\nconst LOCK_REASON_ACTIVATION_EXPIRED = \"انتهت صلاحية مفتاح التفعيل\";\n\nfunction deriveMode(\n tokenValid: boolean,\n meta: AuthMeta,\n activation: StoredActivation | null,\n): OperatingMode {\n if (tokenValid) return \"online\";\n if (meta.activatedOnlineAt != null) return \"offline-degraded\";\n if (activation != null) return \"offline-activated\";\n return \"unactivated\";\n}\n\ninterface AccessComputation {\n state: AccessState;\n graceEndsAt: number | null;\n lockedReason: string | null;\n}\n\n/**\n * آلة الحالة active → grace → locked. الفكرة: للأوضاع الأوفلاين فيه \"نهاية سماح\"\n * (allowanceEnd) — لحد قبلها active، وبعدها بفترة grace، وبعد الـ grace locked.\n * الوضع online دايماً active (لسه بنكلّم السيرفر)، وunactivated دايماً locked.\n */\nfunction computeAccess(\n mode: OperatingMode,\n now: number,\n meta: AuthMeta,\n activation: StoredActivation | null,\n policy: AccessPolicy,\n): AccessComputation {\n if (mode === \"online\") {\n return { state: \"active\", graceEndsAt: null, lockedReason: null };\n }\n if (mode === \"unactivated\") {\n return { state: \"locked\", graceEndsAt: null, lockedReason: LOCK_REASON_UNACTIVATED };\n }\n\n let allowanceEnd: number;\n let graceMs: number;\n let expiredReason: string;\n\n if (mode === \"offline-activated\" && activation) {\n allowanceEnd = activation.claims.expiresAt;\n graceMs = activation.claims.graceMs ?? policy.graceMs;\n expiredReason = LOCK_REASON_ACTIVATION_EXPIRED;\n } else {\n // offline-degraded\n const anchor = meta.lastServerContactAt ?? meta.activatedOnlineAt ?? now;\n allowanceEnd = anchor + policy.maxOfflineMs;\n graceMs = policy.graceMs;\n expiredReason = LOCK_REASON_OFFLINE_TOO_LONG;\n }\n\n if (now < allowanceEnd) {\n return { state: \"active\", graceEndsAt: null, lockedReason: null };\n }\n const lockAt = allowanceEnd + graceMs;\n if (now < lockAt) {\n return { state: \"grace\", graceEndsAt: lockAt, lockedReason: null };\n }\n return { state: \"locked\", graceEndsAt: null, lockedReason: expiredReason };\n}\n","import type { AuthApi } from \"./ports/AuthApi\";\nimport type { AuthVault } from \"./ports/AuthVault\";\nimport type { CashierDirectory } from \"./ports/CashierDirectory\";\nimport type { PinHasher } from \"./ports/PinHasher\";\nimport type { SignatureVerifier } from \"./ports/SignatureVerifier\";\nimport { NoblePinHasher } from \"./crypto/NoblePinHasher\";\nimport { NobleSignatureVerifier } from \"./crypto/NobleSignatureVerifier\";\nimport { TokenManager } from \"./token/TokenManager\";\nimport { PinManager } from \"./pin/PinManager\";\nimport { ActivationManager } from \"./activation/ActivationManager\";\nimport { AuthService } from \"./service/AuthService\";\nimport type { Clock } from \"./time\";\nimport { systemClock } from \"./time\";\nimport type { AccessPolicy } from \"./types\";\n\nexport interface CreateAuthOptions {\n /** التخزين الآمن (حسب المنصة). */\n vault: AuthVault;\n /** عميل OAuth. */\n api: AuthApi;\n /** مصدر hashes الكاشيرية المتزامنة (بيقرأ جدول cashiers من storage). */\n directory: CashierDirectory;\n /** المفتاح العام لقمرة (Ed25519, 32 بايت) للتفعيل الأوفلاين. */\n activationPublicKey: Uint8Array;\n /** هوية الجهاز — لو محدَّدة، مفتاح التفعيل لازم يطابقها. */\n deviceId?: string;\n /** سياسة الـ grace/lock. الافتراضي 30 يوم + 3 أيام grace. */\n policy?: AccessPolicy;\n\n // نقاط حقن اختيارية (اختبار / منصات خاصة)\n hasher?: PinHasher;\n verifier?: SignatureVerifier;\n now?: Clock;\n skewMs?: number;\n maxPinAttempts?: number;\n pinLockoutMs?: number;\n}\n\nexport interface Auth {\n service: AuthService;\n tokens: TokenManager;\n pins: PinManager;\n activation: ActivationManager;\n /** async — للاستخدام العام. */\n getValidToken: () => Promise<string | null>;\n /** متزامن — للربط مع SyncEngine: `{ getAuthToken: auth.getAccessTokenSync }`. */\n getAccessTokenSync: () => string | null;\n}\n\n/**\n * يركّب حزمة الـ auth كاملة بأقل إعداد ممكن. الافتراضيات: crypto من @noble،\n * ساعة النظام، سياسة قياسية. كل حاجة قابلة للحقن.\n *\n * لاحظ: بيحلّ اعتماد دائري خفيف — TokenManager محتاج callback بعد كل اتصال\n * ناجح، والـ callback ده بتاع AuthService. بنمرّر closure متأخّر التنفيذ.\n */\nexport function createAuth(opts: CreateAuthOptions): Auth {\n const now = opts.now ?? systemClock;\n const hasher = opts.hasher ?? new NoblePinHasher();\n const verifier = opts.verifier ?? new NobleSignatureVerifier();\n\n // closure بيشير لـ service اللي هيتعرّف تحت — بينفّذ وقت الـ refresh مش دلوقتي.\n let service: AuthService;\n const tokens = new TokenManager({\n vault: opts.vault,\n api: opts.api,\n now,\n skewMs: opts.skewMs,\n onServerContact: (at) => service.recordServerContact(at),\n });\n\n const pins = new PinManager({\n directory: opts.directory,\n hasher,\n now,\n maxAttempts: opts.maxPinAttempts,\n lockoutMs: opts.pinLockoutMs,\n });\n\n const activation = new ActivationManager({\n vault: opts.vault,\n verifier,\n publicKey: opts.activationPublicKey,\n now,\n deviceId: opts.deviceId,\n });\n\n service = new AuthService({\n vault: opts.vault,\n tokenManager: tokens,\n pinManager: pins,\n activationManager: activation,\n policy: opts.policy,\n now,\n });\n\n return {\n service,\n tokens,\n pins,\n activation,\n getValidToken: () => service.getValidToken(),\n getAccessTokenSync: () => service.getAccessTokenSync(),\n };\n}\n"]}
@@ -0,0 +1,479 @@
1
+ import { P as PinHasher, S as SignatureVerifier } from './SignatureVerifier-ueydiL4D.cjs';
2
+
3
+ /**
4
+ * أنواع الـ auth المشتركة. كل الأوقات = مللي ثانية epoch.
5
+ *
6
+ * حزمة auth مستقلة تماماً عن qumra-pos-storage — الربط بينهم في التطبيق فقط عبر
7
+ * callback واحد: transport.getAuthToken = () => auth.getValidToken().
8
+ */
9
+ /**
10
+ * - online: توكنات قمرة صالحة — بنزامن فعلياً.
11
+ * - offline-degraded: اتفعّل أونلاين قبل كده، التوكنات انتهت/النت مقطوع — بيشتغل
12
+ * على جلسة محلية، الـ sync واقف بس.
13
+ * - offline-activated: مفتاح تفعيل Ed25519 موقّع، اتحقق محلياً من غير ما الجهاز
14
+ * يكلّم السيرفر أبداً.
15
+ * - unactivated: الجهاز لسه ماتفعّلش — لا توكنات ولا مفتاح.
16
+ */
17
+ type OperatingMode = "online" | "offline-degraded" | "offline-activated" | "unactivated";
18
+ /**
19
+ * حالة الوصول = هل نقدر نبيع دلوقتي؟ الانتقال: active → grace → locked.
20
+ * القفل بيمنع البيع الجديد بس — الـ outbox والتاريخ محفوظين دايماً.
21
+ */
22
+ type AccessState = "active" | "grace" | "locked";
23
+ /** رد السيرفر على login/refresh (مدد نسبية بالثواني). */
24
+ interface TokenResponse {
25
+ accessToken: string;
26
+ refreshToken: string;
27
+ /** عمر الـ access token بالثواني (~900 = 15 دقيقة). */
28
+ expiresInSec: number;
29
+ /** عمر الـ refresh token بالثواني (~2592000 = 30 يوم). */
30
+ refreshExpiresInSec: number;
31
+ tokenType?: string;
32
+ }
33
+ /** التوكنات كما تُخزّن — بمواعيد انتهاء مطلقة (ms epoch). */
34
+ interface AuthTokens {
35
+ accessToken: string;
36
+ refreshToken: string;
37
+ accessExpiresAt: number;
38
+ refreshExpiresAt: number;
39
+ tokenType: string;
40
+ }
41
+ /** مدخلات تسجيل الدخول الأونلاين (التاجر/الجهاز). */
42
+ interface LoginInput {
43
+ username: string;
44
+ password: string;
45
+ deviceId?: string;
46
+ }
47
+ /** صف كاشير متزامن من السيرفر — الـ pinHash argon2id. */
48
+ interface CashierRecord {
49
+ id: string;
50
+ name: string;
51
+ /** hash بصيغة PHC القياسية (argon2id) الجاي من السيرفر. */
52
+ pinHash: string;
53
+ active: boolean;
54
+ }
55
+ /** نسخة آمنة للعرض — من غير الـ hash. */
56
+ interface PublicCashier {
57
+ id: string;
58
+ name: string;
59
+ active: boolean;
60
+ }
61
+ /** جلسة الكاشير المفتوحة حالياً على الجهاز. */
62
+ interface CashierSession {
63
+ cashierId: string;
64
+ name: string;
65
+ /** وقت تسجيل الدخول (ms epoch). */
66
+ since: number;
67
+ }
68
+ /** نتيجة محاولة PIN. */
69
+ type PinResult = {
70
+ ok: true;
71
+ cashier: CashierSession;
72
+ } | {
73
+ ok: false;
74
+ reason: "bad-pin" | "unknown-cashier" | "inactive" | "locked";
75
+ /** موجود مع locked — كام مللي ثانية لحد ما القفل يفك. */
76
+ retryAfterMs?: number;
77
+ /** كام محاولة فاضلة قبل القفل (مع bad-pin). */
78
+ attemptsLeft?: number;
79
+ };
80
+ /** حمولة مفتاح التفعيل الموقّع — كل الأوقات ms epoch. */
81
+ interface ActivationClaims {
82
+ merchantId: string;
83
+ deviceId: string;
84
+ /** وقت الإصدار. */
85
+ issuedAt: number;
86
+ /** انتهاء الرخصة — بعده يبدأ grace ثم lock. */
87
+ expiresAt: number;
88
+ /** مدة الـ grace بعد الانتهاء (لو مش موجودة يُستخدم policy.graceMs). */
89
+ graceMs?: number;
90
+ version?: number;
91
+ }
92
+ /** مفتاح تفعيل متحقق منه ومخزّن. */
93
+ interface StoredActivation {
94
+ claims: ActivationClaims;
95
+ /** المفتاح الخام الموقّع (للعرض/إعادة التحقق). */
96
+ key: string;
97
+ /** وقت آخر تحقق ناجح محلياً. */
98
+ verifiedAt: number;
99
+ }
100
+ type ActivationResult = {
101
+ ok: true;
102
+ claims: ActivationClaims;
103
+ } | {
104
+ ok: false;
105
+ reason: "malformed" | "bad-signature" | "expired" | "wrong-device";
106
+ };
107
+ /**
108
+ * قد إيه مسموح للجهاز يفضل أوفلاين قبل ما يتقفل. القيم دي من الاشتراك — الافتراضي
109
+ * معقول لكن مفتاح التفعيل يقدر يتجاوزه (claims.graceMs).
110
+ */
111
+ interface AccessPolicy {
112
+ /** أقصى مدة أوفلاين من غير اتصال بالسيرفر قبل بدء الـ grace (offline-degraded). */
113
+ maxOfflineMs: number;
114
+ /** مدة الـ grace قبل القفل النهائي. */
115
+ graceMs: number;
116
+ }
117
+ /** بيانات وصفية للجلسة تُحفظ في الـ vault. */
118
+ interface AuthMeta {
119
+ /** آخر اتصال ناجح بالسيرفر (login/refresh) — مرساة حساب الأوفلاين. */
120
+ lastServerContactAt: number | null;
121
+ /** أول تفعيل أونلاين ناجح — بيفتح وضع offline-degraded. */
122
+ activatedOnlineAt: number | null;
123
+ }
124
+ interface AuthStatus {
125
+ mode: OperatingMode;
126
+ access: AccessState;
127
+ /** access token صالح دلوقتي؟ */
128
+ tokenValid: boolean;
129
+ /** الكاشير المسجّل حالياً (null = مفيش حد على الشاشة). */
130
+ cashier: CashierSession | null;
131
+ /** لو في grace: امتى هيتحوّل لـ locked (ms epoch). */
132
+ graceEndsAt: number | null;
133
+ /** سبب القفل لو locked. */
134
+ lockedReason: string | null;
135
+ lastServerContactAt: number | null;
136
+ /** التفعيل الأوفلاين لو موجود. */
137
+ activation: StoredActivation | null;
138
+ }
139
+
140
+ /**
141
+ * منفذ الشبكة لـ OAuth. نقطة الحقن الوحيدة للسيرفر — الاختبارات بتمرّر mock،
142
+ * والإنتاج بيمرّر عميل fetch.
143
+ *
144
+ * كل دالة بترمي:
145
+ * - AuthNetworkError عند فشل الشبكة/السيرفر (offline, 5xx) → قابل للإعادة.
146
+ * - AuthRejectedError عند رفض صريح (401/400 invalid_grant) → دائم.
147
+ */
148
+ interface AuthApi {
149
+ /** POST /oauth/token (grant=password) — تسجيل دخول أونلاين. */
150
+ login(input: LoginInput): Promise<TokenResponse>;
151
+ /** POST /oauth/token (grant=refresh_token) — refresh دوّار: بيرجّع refresh جديد. */
152
+ refresh(refreshToken: string): Promise<TokenResponse>;
153
+ /** POST /oauth/revoke — best-effort عند الخروج (اختياري). */
154
+ revoke?(refreshToken: string): Promise<void>;
155
+ }
156
+
157
+ /**
158
+ * منفذ التخزين الآمن للـ auth. التطبيق بيوصّله بتخزين آمن حسب المنصة:
159
+ * - Electron: safeStorage (DPAPI/Keychain) فوق ملف.
160
+ * - Web: IndexedDB (+ WebCrypto لو حبينا نشفّر الـ refresh).
161
+ * - RN: Keychain / EncryptedSharedPreferences.
162
+ *
163
+ * الـ core مابيعرفش عن التشفير — ده مسؤولية الـ vault. القيمة null معناها "امسح".
164
+ * ملاحظة: مسح التوكنات ≠ مسح البيانات التجارية — دي في qumra-pos-storage ومابتتمسّش.
165
+ */
166
+ interface AuthVault {
167
+ loadTokens(): Promise<AuthTokens | null>;
168
+ saveTokens(tokens: AuthTokens | null): Promise<void>;
169
+ loadSession(): Promise<CashierSession | null>;
170
+ saveSession(session: CashierSession | null): Promise<void>;
171
+ loadActivation(): Promise<StoredActivation | null>;
172
+ saveActivation(activation: StoredActivation | null): Promise<void>;
173
+ loadMeta(): Promise<AuthMeta | null>;
174
+ saveMeta(meta: AuthMeta): Promise<void>;
175
+ }
176
+
177
+ /**
178
+ * مصدر hashes الكاشيرية المتزامنة. الحزمة مش بتعرف qumra-pos-storage، فالتطبيق
179
+ * بيوصّل الدالة دي لقراءة جدول cashiers المتزامن من الـ storage.
180
+ *
181
+ * بكده "نفس الكود أونلاين وأوفلاين": PinManager دايماً بيتحقق ضد الـ hash المحلي
182
+ * المتزامن — مفيش نداء سيرفر وقت دخول الكاشير.
183
+ */
184
+ interface CashierDirectory {
185
+ listCashiers(): Promise<CashierRecord[]>;
186
+ }
187
+
188
+ /**
189
+ * كل حسابات الوقت في الـ auth بالمللي ثانية منذ epoch (نفس شكل Date.now).
190
+ * دالة now محقونة علشان الاختبارات تتحكم في الزمن (زي SyncEngine).
191
+ */
192
+ type Clock = () => number;
193
+ declare const systemClock: Clock;
194
+ declare const SECOND = 1000;
195
+ declare const MINUTE: number;
196
+ declare const HOUR: number;
197
+ declare const DAY: number;
198
+
199
+ /**
200
+ * نتيجة محاولة ضمان توكن صالح. غنية علشان AuthService يقدر يفرّق بين "النت مقطوع"
201
+ * (pause، الجلسة تكمل) و "السيرفر رفض" (التوكنات اتمسحت، ندخل مسار grace/lock).
202
+ */
203
+ type RefreshOutcome = {
204
+ status: "valid";
205
+ tokens: AuthTokens;
206
+ } | {
207
+ status: "refreshed";
208
+ tokens: AuthTokens;
209
+ } | {
210
+ status: "network";
211
+ } | {
212
+ status: "rejected";
213
+ } | {
214
+ status: "signed-out";
215
+ };
216
+ interface TokenManagerOptions {
217
+ vault: AuthVault;
218
+ api: AuthApi;
219
+ now?: Clock;
220
+ /**
221
+ * هامش أمان: نعتبر التوكن "منتهي" قبل انتهائه الحقيقي بـ skew — علشان ماننفّذش
222
+ * نداء بتوكن هيقع أثناء الرحلة. افتراضي 30 ثانية.
223
+ */
224
+ skewMs?: number;
225
+ /** يتنادى بعد كل اتصال ناجح بالسيرفر (login/refresh) — AuthService بيحدّث الـ meta. */
226
+ onServerContact?: (at: number) => void | Promise<void>;
227
+ }
228
+ /**
229
+ * TokenVault + OAuth. بيملك دورة حياة التوكنات: login، refresh دوّار single-flight،
230
+ * وينتج التوكن الصالح للـ SyncEngine. القاعدة الذهبية: getValidToken مابيرميش أبداً —
231
+ * null معناها "اعمل pause"، مش استثناء.
232
+ */
233
+ declare class TokenManager {
234
+ private readonly vault;
235
+ private readonly api;
236
+ private readonly now;
237
+ private readonly skewMs;
238
+ private readonly onServerContact;
239
+ /** single-flight: كل النداءات المتزامنة بتشارك نفس عملية الـ refresh. */
240
+ private inflight;
241
+ /**
242
+ * نسخة في الذاكرة من آخر توكنات معروفة. الغرض الوحيد: peekValidToken المتزامن
243
+ * — لأن SyncEngine.getAuthToken متزامن بينما الـ vault async. بتتحدّث مع كل
244
+ * تحميل/حفظ للتوكنات، ودورة الـ refresh الخلفية بتحافظ عليها دافية.
245
+ */
246
+ private cached;
247
+ constructor(opts: TokenManagerOptions);
248
+ /** تسجيل دخول أونلاين. بيرمي AuthRejectedError/AuthNetworkError زي الـ api. */
249
+ login(input: LoginInput): Promise<AuthTokens>;
250
+ /** خروج: إبطال best-effort على السيرفر ثم مسح التوكنات المحلية. */
251
+ logout(): Promise<void>;
252
+ getTokens(): Promise<AuthTokens | null>;
253
+ /** يملأ الكاش من الـ vault مرة (عند الإقلاع) — علشان peek يشتغل قبل أي نداء. */
254
+ primeCache(): Promise<void>;
255
+ /**
256
+ * توكن access صالح متزامن من الكاش — من غير أي I/O أو refresh. ده اللي بيتوصّل
257
+ * لـ SyncEngine.getAuthToken. بيرجّع null لو مفيش كاش أو الكاش منتهي؛ دورة الـ
258
+ * refresh الخلفية (getValidToken) هي اللي بتجدّد الكاش.
259
+ */
260
+ peekValidToken(): string | null;
261
+ /**
262
+ * التوكن الصالح للـ SyncEngine. مابيرميش: أي فشل → null (= pause).
263
+ */
264
+ getValidToken(): Promise<string | null>;
265
+ /**
266
+ * يضمن توكن access صالح: يرجّعه لو صالح، أو يعمل refresh دوّار single-flight.
267
+ * مابيرميش — بيرجّع RefreshOutcome. AuthService بيستخدمه لتحديث حالة الوصول.
268
+ */
269
+ ensureFresh(): Promise<RefreshOutcome>;
270
+ isAccessValid(tokens: AuthTokens): boolean;
271
+ isRefreshValid(tokens: AuthTokens): boolean;
272
+ /** refresh single-flight: نداء واحد بس بيطير حتى لو اتنادى من كذا مكان. */
273
+ private refreshOnce;
274
+ private doRefresh;
275
+ private toTokens;
276
+ }
277
+
278
+ interface PinManagerOptions {
279
+ directory: CashierDirectory;
280
+ hasher: PinHasher;
281
+ now?: Clock;
282
+ /** عدد المحاولات الخاطئة قبل القفل المؤقت. افتراضي 5. */
283
+ maxAttempts?: number;
284
+ /** مدة القفل بعد استنفاد المحاولات. افتراضي دقيقة. */
285
+ lockoutMs?: number;
286
+ }
287
+ /**
288
+ * دخول الكاشير اليومي بالـ PIN المحلي. بيتحقق بـ argon2id ضد الـ hash المتزامن —
289
+ * نفس الكود أونلاين وأوفلاين، مفيش نداء سيرفر. فيه قفل مؤقت لكل كاشير بعد محاولات
290
+ * فاشلة متتالية (حماية من التخمين).
291
+ *
292
+ * ملاحظة: PinManager بيتحقق بس — إدارة الكاشيرية (إضافة/تعديل PIN) من داشبورد
293
+ * التاجر، وبتوصل الجهاز عن طريق مزامنة جدول cashiers.
294
+ */
295
+ declare class PinManager {
296
+ private readonly directory;
297
+ private readonly hasher;
298
+ private readonly now;
299
+ private readonly maxAttempts;
300
+ private readonly lockoutMs;
301
+ private readonly attempts;
302
+ constructor(opts: PinManagerOptions);
303
+ /** قائمة الكاشيرية للعرض (من غير الـ hashes). */
304
+ listCashiers(): Promise<PublicCashier[]>;
305
+ /**
306
+ * يتحقق من PIN كاشير معيّن. النجاح بيصفّر عدّاد محاولاته؛ الفشل بيزوّده ويقفل
307
+ * مؤقتاً عند الوصول للحد.
308
+ */
309
+ verify(cashierId: string, pin: string): Promise<PinResult>;
310
+ /** يفكّ القفل يدوياً (مثلاً المدير سمح). */
311
+ reset(cashierId: string): void;
312
+ private registerFailure;
313
+ private findCashier;
314
+ }
315
+
316
+ /**
317
+ * التفعيل الأوفلاين: مفتاح موقّع بـ Ed25519 يصدره سيرفر قمرة، يتحقق منه الجهاز
318
+ * محلياً بالمفتاح العام المثبّت — بدون أي اتصال بالسيرفر. ده اللي بيسمح بوضع
319
+ * offline-activated لجهاز اتفعّل من غير ما يشوف النت.
320
+ *
321
+ * صيغة المفتاح (زي JWT بس Ed25519): <payloadB64url>.<signatureB64url>
322
+ * التوقيع على بايتات مقطع الـ payload نفسه (نص b64url).
323
+ */
324
+ interface ActivationManagerOptions {
325
+ vault: AuthVault;
326
+ verifier: SignatureVerifier;
327
+ /** المفتاح العام لقمرة (32 بايت Ed25519) — مثبّت في التطبيق. */
328
+ publicKey: Uint8Array;
329
+ now?: Clock;
330
+ /** لو محدَّد، لازم claims.deviceId يطابقه (منع نقل المفتاح لجهاز تاني). */
331
+ deviceId?: string;
332
+ }
333
+ declare class ActivationManager {
334
+ private readonly vault;
335
+ private readonly verifier;
336
+ private readonly publicKey;
337
+ private readonly now;
338
+ private readonly deviceId;
339
+ constructor(opts: ActivationManagerOptions);
340
+ /**
341
+ * يتحقق من مفتاح تفعيل ويخزّنه لو صالح. الترتيب: صيغة → توقيع → الجهاز → الانتهاء.
342
+ * التوقيع بيتفحص قبل أي حاجة تانية علشان مانثقش في أي claim قبل التأكد إنه من قمرة.
343
+ */
344
+ activate(activationKey: string): Promise<ActivationResult>;
345
+ getActivation(): Promise<StoredActivation | null>;
346
+ /**
347
+ * يعيد التحقق من المفتاح المخزّن (توقيع + جهاز) ويحدّث verifiedAt. بيُستدعى عند
348
+ * الإقلاع علشان نتأكد إن المفتاح المخزّن لسه سليم ومش متلاعب فيه.
349
+ */
350
+ revalidateStored(): Promise<ActivationResult | null>;
351
+ clear(): Promise<void>;
352
+ private parse;
353
+ }
354
+
355
+ interface AuthServiceOptions {
356
+ vault: AuthVault;
357
+ tokenManager: TokenManager;
358
+ pinManager: PinManager;
359
+ activationManager: ActivationManager;
360
+ policy?: AccessPolicy;
361
+ now?: Clock;
362
+ }
363
+ type Listener = (status: AuthStatus) => void;
364
+ /**
365
+ * الواجهة الموحّدة للـ auth. بتجمع الثلاث مدراء وبتدير آلة الحالة
366
+ * (active → grace → locked) والأوضاع الثلاثة. بتعرض callback واحد getValidToken
367
+ * للـ SyncEngine، وبثّ حالة onStatusChange للـ UI.
368
+ *
369
+ * مبدأ ثابت: مفيش أي مسار هنا بيمسح بيانات تجارية — أسوأ حالة إن البيع الجديد
370
+ * يتقفل. مسح التوكنات (عند رفض السيرفر) مش مسح للـ outbox أو التاريخ.
371
+ */
372
+ declare class AuthService {
373
+ private readonly vault;
374
+ private readonly now;
375
+ private readonly policy;
376
+ readonly tokens: TokenManager;
377
+ readonly pins: PinManager;
378
+ readonly activation: ActivationManager;
379
+ private readonly listeners;
380
+ private status;
381
+ constructor(opts: AuthServiceOptions);
382
+ /** الإقلاع: يملأ كاش التوكن، يعيد التحقق من مفتاح التفعيل المخزّن، ثم يحسب الحالة. */
383
+ init(): Promise<AuthStatus>;
384
+ /**
385
+ * يحاول تحديث التوكن (لو النت رجع) ثم يعيد حساب الحالة. التطبيق بينادي ده دورياً
386
+ * وبعد أي reconnect. مابيرميش.
387
+ */
388
+ refresh(): Promise<AuthStatus>;
389
+ getStatus(): AuthStatus;
390
+ /** هل مسموح ببيع جديد دلوقتي؟ (locked = لأ). */
391
+ canSell(): boolean;
392
+ onStatusChange(cb: Listener): () => void;
393
+ /** تسجيل دخول أونلاين. بيرمي زي الـ api (rejected/network). */
394
+ onlineLogin(input: LoginInput): Promise<AuthStatus>;
395
+ /** إدخال مفتاح تفعيل أوفلاين. */
396
+ activateOffline(activationKey: string): Promise<ActivationResult>;
397
+ /** خروج التاجر: يمسح التوكنات وجلسة الكاشير (مش البيانات، مش التفعيل). */
398
+ logout(): Promise<AuthStatus>;
399
+ /** callback الوحيد للـ SyncEngine (async). null = pause. */
400
+ getValidToken(): Promise<string | null>;
401
+ /**
402
+ * نسخة متزامنة للـ SyncEngine (getAuthToken بتاعه متزامن). بترجّع آخر توكن صالح
403
+ * من الكاش من غير I/O؛ refresh()/getValidToken الدورية هي اللي بتدفّي الكاش.
404
+ */
405
+ getAccessTokenSync(): string | null;
406
+ /** يُمرَّر للـ TokenManager: يسجّل آخر اتصال ناجح بالسيرفر ويعلّم التفعيل الأونلاين. */
407
+ recordServerContact(at: number): Promise<void>;
408
+ listCashiers(): Promise<PublicCashier[]>;
409
+ cashierLogin(cashierId: string, pin: string): Promise<PinResult>;
410
+ cashierLogout(): Promise<void>;
411
+ private reevaluate;
412
+ private computeStatus;
413
+ }
414
+
415
+ interface CreateAuthOptions {
416
+ /** التخزين الآمن (حسب المنصة). */
417
+ vault: AuthVault;
418
+ /** عميل OAuth. */
419
+ api: AuthApi;
420
+ /** مصدر hashes الكاشيرية المتزامنة (بيقرأ جدول cashiers من storage). */
421
+ directory: CashierDirectory;
422
+ /** المفتاح العام لقمرة (Ed25519, 32 بايت) للتفعيل الأوفلاين. */
423
+ activationPublicKey: Uint8Array;
424
+ /** هوية الجهاز — لو محدَّدة، مفتاح التفعيل لازم يطابقها. */
425
+ deviceId?: string;
426
+ /** سياسة الـ grace/lock. الافتراضي 30 يوم + 3 أيام grace. */
427
+ policy?: AccessPolicy;
428
+ hasher?: PinHasher;
429
+ verifier?: SignatureVerifier;
430
+ now?: Clock;
431
+ skewMs?: number;
432
+ maxPinAttempts?: number;
433
+ pinLockoutMs?: number;
434
+ }
435
+ interface Auth {
436
+ service: AuthService;
437
+ tokens: TokenManager;
438
+ pins: PinManager;
439
+ activation: ActivationManager;
440
+ /** async — للاستخدام العام. */
441
+ getValidToken: () => Promise<string | null>;
442
+ /** متزامن — للربط مع SyncEngine: `{ getAuthToken: auth.getAccessTokenSync }`. */
443
+ getAccessTokenSync: () => string | null;
444
+ }
445
+ /**
446
+ * يركّب حزمة الـ auth كاملة بأقل إعداد ممكن. الافتراضيات: crypto من @noble،
447
+ * ساعة النظام، سياسة قياسية. كل حاجة قابلة للحقن.
448
+ *
449
+ * لاحظ: بيحلّ اعتماد دائري خفيف — TokenManager محتاج callback بعد كل اتصال
450
+ * ناجح، والـ callback ده بتاع AuthService. بنمرّر closure متأخّر التنفيذ.
451
+ */
452
+ declare function createAuth(opts: CreateAuthOptions): Auth;
453
+
454
+ /**
455
+ * الافتراضي: 30 يوم أوفلاين مسموحة (يطابق عمر الـ refresh)، بعدها 3 أيام grace
456
+ * (تحذير للمدير) ثم قفل البيع الجديد. البيانات لا تُمسح أبداً في أي مرحلة.
457
+ */
458
+ declare const DEFAULT_ACCESS_POLICY: AccessPolicy;
459
+
460
+ /**
461
+ * فرق جوهري بين نوعي الفشل — بيحدد سلوك الـ auth بالكامل:
462
+ *
463
+ * - AuthNetworkError: النت/السيرفر مش متاح (offline أو 5xx). قابل لإعادة المحاولة،
464
+ * ومابيمسحش أي توكن. النتيجة: sync يقف مؤقتاً (pause) والجلسة تفضل شغّالة أوفلاين.
465
+ *
466
+ * - AuthRejectedError: السيرفر رفض صراحةً (401/400 invalid_grant، refresh متبطّل،
467
+ * كلمة سر غلط). دائم — إعادة المحاولة مش هتفيد. النتيجة: التوكنات تتمسح والجلسة
468
+ * تتحوّل للوضع الأوفلاين/المقفول. البيانات التجارية لا تُمسح أبداً.
469
+ */
470
+ declare class AuthNetworkError extends Error {
471
+ constructor(message: string, cause?: unknown);
472
+ }
473
+ declare class AuthRejectedError extends Error {
474
+ /** كود السيرفر لو متاح (invalid_grant, invalid_credentials …). */
475
+ readonly code: string | undefined;
476
+ constructor(message: string, code?: string, cause?: unknown);
477
+ }
478
+
479
+ export { type AccessPolicy, type AccessState, type ActivationClaims, ActivationManager, type ActivationManagerOptions, type ActivationResult, type Auth, type AuthApi, type AuthMeta, AuthNetworkError, AuthRejectedError, AuthService, type AuthServiceOptions, type AuthStatus, type AuthTokens, type AuthVault, type CashierDirectory, type CashierRecord, type CashierSession, type Clock, type CreateAuthOptions, DAY, DEFAULT_ACCESS_POLICY, HOUR, type LoginInput, MINUTE, type OperatingMode, PinHasher, PinManager, type PinManagerOptions, type PinResult, type PublicCashier, type RefreshOutcome, SECOND, SignatureVerifier, type StoredActivation, TokenManager, type TokenManagerOptions, type TokenResponse, createAuth, systemClock };