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,479 @@
1
+ import { P as PinHasher, S as SignatureVerifier } from './SignatureVerifier-ueydiL4D.js';
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 };