@palbase/web 4.0.1 → 4.0.2
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/{analytics-facade-DwOtlXPP.d.cts → analytics-facade-CaluA4bW.d.cts} +26 -1
- package/dist/{analytics-facade-Nk6J9Ncm.d.ts → analytics-facade-Cp3d4QI-.d.ts} +26 -1
- package/dist/{chunk-NXEPAEF5.js → chunk-CFDU23TB.js} +3 -3
- package/dist/chunk-CFDU23TB.js.map +1 -0
- package/dist/{chunk-TGDS6VMT.js → chunk-TW6YN354.js} +58 -6
- package/dist/chunk-TW6YN354.js.map +1 -0
- package/dist/gen/cli.cjs +5 -5
- package/dist/gen/cli.cjs.map +1 -1
- package/dist/gen/cli.js +5 -5
- package/dist/gen/cli.js.map +1 -1
- package/dist/index.cjs +55 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/internal.cjs +57 -5
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +3 -3
- package/dist/internal.d.ts +3 -3
- package/dist/internal.js +2 -2
- package/dist/next/client.cjs +57 -5
- package/dist/next/client.cjs.map +1 -1
- package/dist/next/client.js +2 -2
- package/dist/next/index.cjs +58 -6
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +2 -2
- package/dist/next/index.d.ts +2 -2
- package/dist/next/index.js +2 -2
- package/dist/{pb-FG_nV7NR.d.ts → pb-DUK5qy81.d.ts} +1 -1
- package/dist/{pb-C9v5dEO6.d.cts → pb-DvV6ftmf.d.cts} +1 -1
- package/dist/react/index.cjs +10 -2
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-NXEPAEF5.js.map +0 -1
- package/dist/chunk-TGDS6VMT.js.map +0 -1
|
@@ -1663,7 +1663,13 @@ type AuthChangeEvent = {
|
|
|
1663
1663
|
user: AuthUser;
|
|
1664
1664
|
} | {
|
|
1665
1665
|
type: 'signedOut';
|
|
1666
|
-
|
|
1666
|
+
/**
|
|
1667
|
+
* `userInitiated` — pb.auth.signOut(); `sessionExpired` — a refresh
|
|
1668
|
+
* ultimately failed; `accountDeleted` — this device ran deleteAccount();
|
|
1669
|
+
* `sessionInvalid` — a server-side session kill (erased/revoked subject)
|
|
1670
|
+
* was observed on a request and the client tore down reactively.
|
|
1671
|
+
*/
|
|
1672
|
+
reason: 'userInitiated' | 'sessionExpired' | 'accountDeleted' | 'sessionInvalid';
|
|
1667
1673
|
} | {
|
|
1668
1674
|
type: 'tokenRefreshed';
|
|
1669
1675
|
};
|
|
@@ -1672,6 +1678,7 @@ declare class PalbeAuth {
|
|
|
1672
1678
|
private readonly rt;
|
|
1673
1679
|
private cachedUser;
|
|
1674
1680
|
private signingOut;
|
|
1681
|
+
private nextSignOutReason;
|
|
1675
1682
|
private signingIn;
|
|
1676
1683
|
private signedInState;
|
|
1677
1684
|
private hydratingUser;
|
|
@@ -1690,6 +1697,24 @@ declare class PalbeAuth {
|
|
|
1690
1697
|
password: string;
|
|
1691
1698
|
}): Promise<AuthSuccess>;
|
|
1692
1699
|
signOut(): Promise<void>;
|
|
1700
|
+
/**
|
|
1701
|
+
* Self-service account erasure ("right to be forgotten"). Calls palauth
|
|
1702
|
+
* `DELETE /auth/user` (session-authed + fresh re-auth): password users pass
|
|
1703
|
+
* `{ password }`; passwordless/OAuth users rely on a freshly stepped-up
|
|
1704
|
+
* session. On 202 the erasure workflow is durably queued AND every session is
|
|
1705
|
+
* already revoked server-side — so we tear down local state (mirroring
|
|
1706
|
+
* `signOut()`'s clear, minus the pointless `/logout`) and emit
|
|
1707
|
+
* `signedOut{reason:'accountDeleted'}`.
|
|
1708
|
+
*
|
|
1709
|
+
* On 401 `reauth_required` / 503 `not_configured` (or `erasure_unavailable`)
|
|
1710
|
+
* the request throws BEFORE the teardown line, so the local session is left
|
|
1711
|
+
* fully intact — the deletion did not happen and the user is still signed in.
|
|
1712
|
+
*/
|
|
1713
|
+
deleteAccount(params?: {
|
|
1714
|
+
password?: string;
|
|
1715
|
+
}): Promise<{
|
|
1716
|
+
erasureId: string;
|
|
1717
|
+
}>;
|
|
1693
1718
|
getUser(): Promise<AuthUser>;
|
|
1694
1719
|
refreshUser(): Promise<AuthUser>;
|
|
1695
1720
|
/**
|
|
@@ -1663,7 +1663,13 @@ type AuthChangeEvent = {
|
|
|
1663
1663
|
user: AuthUser;
|
|
1664
1664
|
} | {
|
|
1665
1665
|
type: 'signedOut';
|
|
1666
|
-
|
|
1666
|
+
/**
|
|
1667
|
+
* `userInitiated` — pb.auth.signOut(); `sessionExpired` — a refresh
|
|
1668
|
+
* ultimately failed; `accountDeleted` — this device ran deleteAccount();
|
|
1669
|
+
* `sessionInvalid` — a server-side session kill (erased/revoked subject)
|
|
1670
|
+
* was observed on a request and the client tore down reactively.
|
|
1671
|
+
*/
|
|
1672
|
+
reason: 'userInitiated' | 'sessionExpired' | 'accountDeleted' | 'sessionInvalid';
|
|
1667
1673
|
} | {
|
|
1668
1674
|
type: 'tokenRefreshed';
|
|
1669
1675
|
};
|
|
@@ -1672,6 +1678,7 @@ declare class PalbeAuth {
|
|
|
1672
1678
|
private readonly rt;
|
|
1673
1679
|
private cachedUser;
|
|
1674
1680
|
private signingOut;
|
|
1681
|
+
private nextSignOutReason;
|
|
1675
1682
|
private signingIn;
|
|
1676
1683
|
private signedInState;
|
|
1677
1684
|
private hydratingUser;
|
|
@@ -1690,6 +1697,24 @@ declare class PalbeAuth {
|
|
|
1690
1697
|
password: string;
|
|
1691
1698
|
}): Promise<AuthSuccess>;
|
|
1692
1699
|
signOut(): Promise<void>;
|
|
1700
|
+
/**
|
|
1701
|
+
* Self-service account erasure ("right to be forgotten"). Calls palauth
|
|
1702
|
+
* `DELETE /auth/user` (session-authed + fresh re-auth): password users pass
|
|
1703
|
+
* `{ password }`; passwordless/OAuth users rely on a freshly stepped-up
|
|
1704
|
+
* session. On 202 the erasure workflow is durably queued AND every session is
|
|
1705
|
+
* already revoked server-side — so we tear down local state (mirroring
|
|
1706
|
+
* `signOut()`'s clear, minus the pointless `/logout`) and emit
|
|
1707
|
+
* `signedOut{reason:'accountDeleted'}`.
|
|
1708
|
+
*
|
|
1709
|
+
* On 401 `reauth_required` / 503 `not_configured` (or `erasure_unavailable`)
|
|
1710
|
+
* the request throws BEFORE the teardown line, so the local session is left
|
|
1711
|
+
* fully intact — the deletion did not happen and the user is still signed in.
|
|
1712
|
+
*/
|
|
1713
|
+
deleteAccount(params?: {
|
|
1714
|
+
password?: string;
|
|
1715
|
+
}): Promise<{
|
|
1716
|
+
erasureId: string;
|
|
1717
|
+
}>;
|
|
1693
1718
|
getUser(): Promise<AuthUser>;
|
|
1694
1719
|
refreshUser(): Promise<AuthUser>;
|
|
1695
1720
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/api-key.ts
|
|
2
|
-
var API_KEY_RE = /^pb_([a-z0-9]
|
|
3
|
-
var PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]
|
|
2
|
+
var API_KEY_RE = /^pb_([a-z0-9]{4,24})_[cs][A-Za-z0-9]{20}$/;
|
|
3
|
+
var PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]{4,24})_c[A-Za-z0-9]{20}$/;
|
|
4
4
|
function environmentRefFromApiKey(apiKey) {
|
|
5
5
|
const m = API_KEY_RE.exec(apiKey);
|
|
6
6
|
return m ? m[1] ?? "" : "";
|
|
@@ -14,4 +14,4 @@ export {
|
|
|
14
14
|
environmentRefFromApiKey,
|
|
15
15
|
environmentRefFromPublishableApiKey
|
|
16
16
|
};
|
|
17
|
-
//# sourceMappingURL=chunk-
|
|
17
|
+
//# sourceMappingURL=chunk-CFDU23TB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api-key.ts"],"sourcesContent":["/**\n * `pb_<environmentRef>_<scope><random>` → environmentRef ('' if malformed).\n * Utility for callers that only have a raw key. App-bound runtime storage and\n * palbe/next cookie naming use the explicit `PalbeConfig.environmentRef` emitted\n * by `palbe-gen`.\n *\n * The key is shape-validated (prefix `pb`, a 4-24 character lowercase ASCII\n * alphanumeric environmentRef, and a `<scope><20-base62-random>` secret segment\n * where scope ∈ {c,s}) before a ref is returned. A structurally-invalid key returns\n * '' so session storage stays\n * UNSCOPED rather than getting bound to a partially-parsed ref — a loose parse\n * (e.g. `pb_victim_cXX`) must not scope persisted sessions to `victim` and\n * hydrate a session belonging to a different, real key. The backend remains the\n * authority that rejects a bad key on the first request; this keeps the client's\n * local session-storage scoping honest. (Audit finding apikey-ref-mismatch.)\n */\nconst API_KEY_RE = /^pb_([a-z0-9]{4,24})_[cs][A-Za-z0-9]{20}$/;\nconst PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]{4,24})_c[A-Za-z0-9]{20}$/;\n\nexport function environmentRefFromApiKey(apiKey: string): string {\n const m = API_KEY_RE.exec(apiKey);\n return m ? (m[1] ?? '') : '';\n}\n\n/** Internal app-runtime parser: browser config accepts publishable keys only. */\nexport function environmentRefFromPublishableApiKey(apiKey: string): string {\n const match = PUBLISHABLE_API_KEY_RE.exec(apiKey);\n return match ? (match[1] ?? '') : '';\n}\n"],"mappings":";AAgBA,IAAM,aAAa;AACnB,IAAM,yBAAyB;AAExB,SAAS,yBAAyB,QAAwB;AAC/D,QAAM,IAAI,WAAW,KAAK,MAAM;AAChC,SAAO,IAAK,EAAE,CAAC,KAAK,KAAM;AAC5B;AAGO,SAAS,oCAAoC,QAAwB;AAC1E,QAAM,QAAQ,uBAAuB,KAAK,MAAM;AAChD,SAAO,QAAS,MAAM,CAAC,KAAK,KAAM;AACpC;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
environmentRefFromPublishableApiKey
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-CFDU23TB.js";
|
|
4
4
|
import {
|
|
5
5
|
__export
|
|
6
6
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -20,7 +20,7 @@ var PalbaseError = class extends Error {
|
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
var PALBASE_DEFAULT_HOST = "api.palbase.studio";
|
|
23
|
-
var API_KEY_RE = /^pb_([a-z0-9]
|
|
23
|
+
var API_KEY_RE = /^pb_([a-z0-9]{4,24})_c[A-Za-z0-9]{20}$/;
|
|
24
24
|
function parseEnvironmentRef(apiKey) {
|
|
25
25
|
return API_KEY_RE.exec(apiKey)?.[1] ?? null;
|
|
26
26
|
}
|
|
@@ -397,6 +397,11 @@ var PERF_EXCLUDED_PREFIX = "/v1/analytics/";
|
|
|
397
397
|
function isSelfTraced(path) {
|
|
398
398
|
return path.startsWith(PERF_EXCLUDED_PREFIX);
|
|
399
399
|
}
|
|
400
|
+
function isSessionKilled(status, code) {
|
|
401
|
+
if (status === 401) return code === "session_revoked";
|
|
402
|
+
if (status === 403) return code === "subject_fenced" || code === "subject_erased";
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
400
405
|
function nowMs() {
|
|
401
406
|
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
402
407
|
}
|
|
@@ -432,7 +437,7 @@ async function palbeRequest(rt, method, path, spec = {}) {
|
|
|
432
437
|
let res;
|
|
433
438
|
try {
|
|
434
439
|
res = await attempt();
|
|
435
|
-
if (res.error?.status === 401 && rt.tokenManager.getRefreshToken() && rt.tokenManager.refreshFunction) {
|
|
440
|
+
if (res.error?.status === 401 && res.error.code !== "session_revoked" && rt.tokenManager.getRefreshToken() && rt.tokenManager.refreshFunction) {
|
|
436
441
|
try {
|
|
437
442
|
await rt.tokenManager.refreshSession();
|
|
438
443
|
} catch (refreshErr) {
|
|
@@ -452,6 +457,9 @@ async function palbeRequest(rt, method, path, spec = {}) {
|
|
|
452
457
|
if (!isAbort(e)) record(asPalbaseError(e)?.status ?? 0);
|
|
453
458
|
throw e;
|
|
454
459
|
}
|
|
460
|
+
if (res.error && isSessionKilled(res.error.status, res.error.code)) {
|
|
461
|
+
rt.auth.reactiveTeardown();
|
|
462
|
+
}
|
|
455
463
|
record(res.error?.status ?? 200);
|
|
456
464
|
return unwrap(res);
|
|
457
465
|
}
|
|
@@ -1426,7 +1434,8 @@ var PalbeAuth = class {
|
|
|
1426
1434
|
if (!this.signedInState) return;
|
|
1427
1435
|
this.signedInState = false;
|
|
1428
1436
|
this.cachedUser = null;
|
|
1429
|
-
const reason = this.signingOut ? "userInitiated" : "sessionExpired";
|
|
1437
|
+
const reason = this.nextSignOutReason ?? (this.signingOut ? "userInitiated" : "sessionExpired");
|
|
1438
|
+
this.nextSignOutReason = null;
|
|
1430
1439
|
this.emitState({ status: "signedOut" });
|
|
1431
1440
|
this.emitEvent({ type: "signedOut", reason });
|
|
1432
1441
|
} else if (event === "TOKEN_REFRESHED") {
|
|
@@ -1439,6 +1448,10 @@ var PalbeAuth = class {
|
|
|
1439
1448
|
rt;
|
|
1440
1449
|
cachedUser = null;
|
|
1441
1450
|
signingOut = false;
|
|
1451
|
+
// Explicit signedOut reason pinned for the NEXT session clear (deleteAccount /
|
|
1452
|
+
// reactiveTeardown set it before clearSession; the SIGNED_OUT handler consumes
|
|
1453
|
+
// it exactly once, then resets to null → normal signOut/expiry split resumes).
|
|
1454
|
+
nextSignOutReason = null;
|
|
1442
1455
|
signingIn = false;
|
|
1443
1456
|
// suppresses AuthClient's TOKEN_REFRESHED during re-signIn
|
|
1444
1457
|
signedInState = false;
|
|
@@ -1486,6 +1499,45 @@ var PalbeAuth = class {
|
|
|
1486
1499
|
this.cachedUser = null;
|
|
1487
1500
|
}
|
|
1488
1501
|
}
|
|
1502
|
+
/**
|
|
1503
|
+
* Self-service account erasure ("right to be forgotten"). Calls palauth
|
|
1504
|
+
* `DELETE /auth/user` (session-authed + fresh re-auth): password users pass
|
|
1505
|
+
* `{ password }`; passwordless/OAuth users rely on a freshly stepped-up
|
|
1506
|
+
* session. On 202 the erasure workflow is durably queued AND every session is
|
|
1507
|
+
* already revoked server-side — so we tear down local state (mirroring
|
|
1508
|
+
* `signOut()`'s clear, minus the pointless `/logout`) and emit
|
|
1509
|
+
* `signedOut{reason:'accountDeleted'}`.
|
|
1510
|
+
*
|
|
1511
|
+
* On 401 `reauth_required` / 503 `not_configured` (or `erasure_unavailable`)
|
|
1512
|
+
* the request throws BEFORE the teardown line, so the local session is left
|
|
1513
|
+
* fully intact — the deletion did not happen and the user is still signed in.
|
|
1514
|
+
*/
|
|
1515
|
+
async deleteAccount(params = {}) {
|
|
1516
|
+
const res = await palbeRequest(this.rt, "DELETE", "/auth/user", {
|
|
1517
|
+
body: params.password ? { password: params.password } : {}
|
|
1518
|
+
});
|
|
1519
|
+
this.nextSignOutReason = "accountDeleted";
|
|
1520
|
+
this.rt.tokenManager.clearSession();
|
|
1521
|
+
this.rt.storage.clear();
|
|
1522
|
+
this.cachedUser = null;
|
|
1523
|
+
return { erasureId: res.erasure_id };
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* @internal — invoked by the transport choke point (`request.ts`), not app code.
|
|
1527
|
+
* Reactive teardown when the server reports the session is gone: a 403
|
|
1528
|
+
* `subject_fenced`/`subject_erased` (subject being erased) or a 401
|
|
1529
|
+
* `session_revoked`. Clears local state and emits
|
|
1530
|
+
* `signedOut{reason:'sessionInvalid'}` exactly once (deduped by
|
|
1531
|
+
* `signedInState`). An ordinary 403 authz denial does NOT reach here —
|
|
1532
|
+
* `request.ts` matches only the exact session-kill codes.
|
|
1533
|
+
*/
|
|
1534
|
+
reactiveTeardown() {
|
|
1535
|
+
if (!this.signedInState) return;
|
|
1536
|
+
this.nextSignOutReason = "sessionInvalid";
|
|
1537
|
+
this.rt.tokenManager.clearSession();
|
|
1538
|
+
this.rt.storage.clear();
|
|
1539
|
+
this.cachedUser = null;
|
|
1540
|
+
}
|
|
1489
1541
|
async getUser() {
|
|
1490
1542
|
const raw = await palbeRequest(this.rt, "GET", "/auth/user");
|
|
1491
1543
|
return mapWireUser(raw);
|
|
@@ -8939,7 +8991,7 @@ function defaultSessionStorage(key) {
|
|
|
8939
8991
|
}
|
|
8940
8992
|
|
|
8941
8993
|
// src/version.ts
|
|
8942
|
-
var VERSION = "4.0.
|
|
8994
|
+
var VERSION = "4.0.2";
|
|
8943
8995
|
|
|
8944
8996
|
// src/runtime.ts
|
|
8945
8997
|
function buildRuntime(config) {
|
|
@@ -9366,4 +9418,4 @@ export {
|
|
|
9366
9418
|
pb,
|
|
9367
9419
|
createBoundClient
|
|
9368
9420
|
};
|
|
9369
|
-
//# sourceMappingURL=chunk-
|
|
9421
|
+
//# sourceMappingURL=chunk-TW6YN354.js.map
|