@farthershore/farthershore-js 0.10.0 → 0.12.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.
- package/CHANGELOG.md +41 -0
- package/README.md +1 -1
- package/dist/client.d.ts +10 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -0
- package/dist/client.js.map +1 -1
- package/dist/component-permissions.d.ts +6 -0
- package/dist/component-permissions.d.ts.map +1 -0
- package/dist/component-permissions.js +38 -0
- package/dist/component-permissions.js.map +1 -0
- package/dist/components/access-denied.d.ts +38 -0
- package/dist/components/access-denied.d.ts.map +1 -0
- package/dist/components/access-denied.js +48 -0
- package/dist/components/access-denied.js.map +1 -0
- package/dist/components/auth-guard.d.ts +44 -12
- package/dist/components/auth-guard.d.ts.map +1 -1
- package/dist/components/auth-guard.js +28 -12
- package/dist/components/auth-guard.js.map +1 -1
- package/dist/components/auth.d.ts +27 -0
- package/dist/components/auth.d.ts.map +1 -1
- package/dist/components/auth.js +176 -3
- package/dist/components/auth.js.map +1 -1
- package/dist/components/docs.css +1 -2
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/permission-gate.d.ts +70 -0
- package/dist/components/permission-gate.d.ts.map +1 -0
- package/dist/components/permission-gate.js +105 -0
- package/dist/components/permission-gate.js.map +1 -0
- package/dist/components/product-docs/product-docs-shell.d.ts.map +1 -1
- package/dist/components/product-docs/product-docs-shell.js +13 -1
- package/dist/components/product-docs/product-docs-shell.js.map +1 -1
- package/dist/components/styles.css +45 -0
- package/dist/config.d.ts +20 -11
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -7
- package/dist/config.js.map +1 -1
- package/dist/deny-codes.d.ts +2 -0
- package/dist/deny-codes.d.ts.map +1 -1
- package/dist/deny-codes.js +7 -0
- package/dist/deny-codes.js.map +1 -1
- package/dist/errors/index.d.ts +28 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +55 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.js +2 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/permissions.d.ts +32 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +57 -0
- package/dist/permissions.js.map +1 -0
- package/dist/react/hooks.d.ts +4 -0
- package/dist/react/hooks.d.ts.map +1 -1
- package/dist/react/hooks.js +5 -0
- package/dist/react/hooks.js.map +1 -1
- package/dist/resources/account.d.ts +64 -1
- package/dist/resources/account.d.ts.map +1 -1
- package/dist/resources/account.js +96 -1
- package/dist/resources/account.js.map +1 -1
- package/dist/test-utils/mock-client.d.ts.map +1 -1
- package/dist/test-utils/mock-client.js +17 -2
- package/dist/test-utils/mock-client.js.map +1 -1
- package/dist/types.d.ts +65 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,47 @@
|
|
|
3
3
|
All notable changes to `@farthershore/farthershore-js` are documented here.
|
|
4
4
|
This project adheres to Semantic Versioning (pre-1.0: minors may break).
|
|
5
5
|
|
|
6
|
+
## [0.12.0] - 2026-07-06
|
|
7
|
+
|
|
8
|
+
Unified Authorization — permission gating as a first-class UI primitive.
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `usePermissionGate(permission)` + `<PermissionGate permission mode fallback>`
|
|
13
|
+
(`hide | disable | readOnly | fallback`): declarative RBAC gating for ANY
|
|
14
|
+
component — managed template or fully custom builder UI — with a
|
|
15
|
+
no-flash `loading` status until the auth claim resolves. `disable` renders
|
|
16
|
+
a real `<fieldset disabled>` with `inert` (applied via ref, React 18 + 19
|
|
17
|
+
compatible); `readOnly` exposes `PermissionReadOnlyContext`.
|
|
18
|
+
- `<AccessDenied variant requiredPermission onRequestAccess>` — the deny
|
|
19
|
+
surface that names the missing `<subject>:<verb>`.
|
|
20
|
+
- Component self-gating: SDK data components gate on their own permission key
|
|
21
|
+
(`componentPermission` map — `audit_log:read`, `team:read`, `apikey:read`,
|
|
22
|
+
…), overridable by prop.
|
|
23
|
+
- `useFsAuth()` exposes `authzLoaded`; `hasPermission` now evaluates the
|
|
24
|
+
canonical `permissionSatisfies` rule (`*` / `<subject>:*` / exact) plus the
|
|
25
|
+
`permissionWithin` subset-check parity.
|
|
26
|
+
- Deny codes: `permission_denied`, `permission_unresolved`, and
|
|
27
|
+
`context_unverified` join the typed gateway deny-code set.
|
|
28
|
+
|
|
29
|
+
## [0.11.0] - 2026-07-04
|
|
30
|
+
|
|
31
|
+
Managed RBAC frontend.
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- `useFsAuth()` now returns `{ roles, permissions, hasPermission }` (from
|
|
36
|
+
`/portal/me`) for UX-level gating — the edge remains the enforcement boundary.
|
|
37
|
+
- `requirePermission` prop on `<AuthGuard>`.
|
|
38
|
+
- RBAC client methods (org RBAC settings, role CRUD, member role assignment)
|
|
39
|
+
and the audit-log **"Access control"** category in `<AuditLogTable />`.
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
43
|
+
- Clerk dev-instance satellite-login session recovery — auto-recovers the
|
|
44
|
+
"click login → had to refresh to see the portal" case (one-shot, cookie-gated,
|
|
45
|
+
no-op on the primary domain).
|
|
46
|
+
|
|
6
47
|
## [0.10.0] - 2026-07-02
|
|
7
48
|
|
|
8
49
|
Frontend SDK ergonomics redesign — the headless client + hooks are now the
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
The **Farther Shore Frontend SDK** — the browser + React integration layer for
|
|
4
4
|
your product's subscriber portal.
|
|
5
5
|
|
|
6
|
-
> **Status: `0.
|
|
6
|
+
> **Status: `0.12.0`.** Pre-1.0 (`0.x`): a minor bump (e.g. `0.9.x` → `0.10.0`)
|
|
7
7
|
> may include breaking changes, so a caret range is unsafe — **pin this package
|
|
8
8
|
> exactly** (`0.9.0`) or use a patch-only tilde (`~0.9.0`). Changes are recorded
|
|
9
9
|
> in [`CHANGELOG.md`](./CHANGELOG.md).
|
package/dist/client.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { type KeysResource } from "./resources/keys.js";
|
|
|
8
8
|
import { type UsageResource } from "./resources/usage.js";
|
|
9
9
|
import { type BillingResource } from "./resources/billing.js";
|
|
10
10
|
import { type PlansResource } from "./resources/plans.js";
|
|
11
|
-
import { type AuditLogsResource, type OrganizationsResource, type TeamResource } from "./resources/account.js";
|
|
11
|
+
import { type AuditLogsResource, type OrganizationsResource, type RbacResource, type TeamResource } from "./resources/account.js";
|
|
12
12
|
import { type FeatureHandle, type GatewayRequestInit } from "./resources/feature.js";
|
|
13
13
|
import { type EntitlementsResource, type FeaturesResource } from "./resources/entitlements.js";
|
|
14
14
|
import { type ApiResource } from "./resources/api.js";
|
|
@@ -39,10 +39,10 @@ export interface PrefetchSurface {
|
|
|
39
39
|
export interface FartherShoreClient {
|
|
40
40
|
/** The client's resolved runtime context (coreUrl, portalHost, businessId,
|
|
41
41
|
* auth/scoping state, …). `coreUrl`/`portalHost` are LAZY getters — reading
|
|
42
|
-
* them performs the `window.__FS_CONFIG__`/`location.host` resolution
|
|
43
|
-
* `coreUrl`
|
|
44
|
-
* snapshot of the client's current state. Mainly for
|
|
45
|
-
* prefer the typed resources for actual calls. */
|
|
42
|
+
* them performs the `window.__FS_CONFIG__`/`location.host` resolution
|
|
43
|
+
* (`coreUrl` falls back to the production platform); everything else is a
|
|
44
|
+
* live snapshot of the client's current state. Mainly for
|
|
45
|
+
* introspection/tests — prefer the typed resources for actual calls. */
|
|
46
46
|
readonly context: ClientContext;
|
|
47
47
|
/** Resolve + cache the business/env/gateway for the current portal host. Safe
|
|
48
48
|
* to call repeatedly (memoized). */
|
|
@@ -114,6 +114,11 @@ export interface FartherShoreClient {
|
|
|
114
114
|
readonly organizations: OrganizationsResource;
|
|
115
115
|
/** Team management on the current subscription. */
|
|
116
116
|
readonly team: TeamResource;
|
|
117
|
+
/** Managed-RBAC management on the current subscription (settings, the
|
|
118
|
+
* derived permission catalog, role CRUD) — team-org OWNER/ADMIN only.
|
|
119
|
+
* Configures UX + minted-token claims; the EDGE `permission` constraint
|
|
120
|
+
* is the security boundary. */
|
|
121
|
+
readonly rbac: RbacResource;
|
|
117
122
|
/** The subscriber-side audit log (cursor-paged). */
|
|
118
123
|
readonly auditLogs: AuditLogsResource;
|
|
119
124
|
/** Current subscriber entitlement maps from the pinned plan version. */
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAEnB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAA2B,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAW,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAE1D,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAGL,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EAClB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACxB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAKlC,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/D;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,qEAAqE;IACrE,IAAI,IAAI,IAAI,CAAC;IACb,0EAA0E;IAC1E,EAAE,IAAI,IAAI,CAAC;IACX,gFAAgF;IAChF,KAAK,IAAI,IAAI,CAAC;IACd,6BAA6B;IAC7B,OAAO,IAAI,IAAI,CAAC;IAChB,qDAAqD;IACrD,YAAY,IAAI,IAAI,CAAC;IACrB,uDAAuD;IACvD,aAAa,IAAI,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,4EAA4E;AAC5E,+EAA+E;AAC/E,sCAAsC;AAEtC,OAAO,EAGL,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAoB,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,OAAO,EAAuB,MAAM,YAAY,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EACL,0BAA0B,GAE3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,sBAAsB,GAEvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,GAEtB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAqB,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAsB,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EACL,qBAAqB,GAEtB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAsB,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EACL,oBAAoB,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Manifest component id → default self-gate permission (or null for none). */
|
|
2
|
+
export declare const COMPONENT_PERMISSIONS: Readonly<Record<string, string | null>>;
|
|
3
|
+
/** The default self-gate permission for a component id, or null when it has
|
|
4
|
+
* none (public / feature-scoped). Unknown ids also return null. */
|
|
5
|
+
export declare function componentPermission(componentId: string): string | null;
|
|
6
|
+
//# sourceMappingURL=component-permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-permissions.d.ts","sourceRoot":"","sources":["../src/component-permissions.ts"],"names":[],"mappings":"AAiBA,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAczE,CAAC;AAEF;oEACoE;AACpE,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEtE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// component-permissions.ts (UA-1)
|
|
3
|
+
//
|
|
4
|
+
// The SELF-GATE map: each manifest component id → the default `<subject>:<verb>`
|
|
5
|
+
// permission a data component requires to render its data. SDK data components
|
|
6
|
+
// consult this so a registry-driven render (the template's component-registry,
|
|
7
|
+
// or any builder frontend that mounts a component by id) gates on the right
|
|
8
|
+
// permission with zero per-call wiring. A manifest `permission` override on the
|
|
9
|
+
// component always wins; `null` here means "no default self-gate" (the
|
|
10
|
+
// component is either public or feature-scoped and takes its key from props).
|
|
11
|
+
//
|
|
12
|
+
// These are the MANAGED permission keys from the unified grammar
|
|
13
|
+
// (`@farthershore/contracts/authz/verbs`) — the same tokens the edge enforces —
|
|
14
|
+
// so a component that hides itself for `apikey:read` is consistent end-to-end
|
|
15
|
+
// with the gateway denying `apikey:read` on the API.
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/** Manifest component id → default self-gate permission (or null for none). */
|
|
18
|
+
export const COMPONENT_PERMISSIONS = {
|
|
19
|
+
plans_table: "subscription:read",
|
|
20
|
+
usage_card: "usage:read",
|
|
21
|
+
api_keys_panel: "apikey:read",
|
|
22
|
+
billing_summary: "invoice:read",
|
|
23
|
+
credit_balance: "invoice:read",
|
|
24
|
+
// feature_panel renders a builder feature — its permission is the feature's
|
|
25
|
+
// own `<feature>:read`, supplied via props/manifest, not a fixed managed key.
|
|
26
|
+
feature_panel: null,
|
|
27
|
+
// business_docs is public-facing product documentation.
|
|
28
|
+
business_docs: null,
|
|
29
|
+
audit_log: "audit_log:read",
|
|
30
|
+
team_panel: "team:read",
|
|
31
|
+
markdown: null,
|
|
32
|
+
};
|
|
33
|
+
/** The default self-gate permission for a component id, or null when it has
|
|
34
|
+
* none (public / feature-scoped). Unknown ids also return null. */
|
|
35
|
+
export function componentPermission(componentId) {
|
|
36
|
+
return COMPONENT_PERMISSIONS[componentId] ?? null;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=component-permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-permissions.js","sourceRoot":"","sources":["../src/component-permissions.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,kCAAkC;AAClC,EAAE;AACF,iFAAiF;AACjF,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,gFAAgF;AAChF,uEAAuE;AACvE,8EAA8E;AAC9E,EAAE;AACF,iEAAiE;AACjE,gFAAgF;AAChF,8EAA8E;AAC9E,qDAAqD;AACrD,8EAA8E;AAE9E,+EAA+E;AAC/E,MAAM,CAAC,MAAM,qBAAqB,GAA4C;IAC5E,WAAW,EAAE,mBAAmB;IAChC,UAAU,EAAE,YAAY;IACxB,cAAc,EAAE,aAAa;IAC7B,eAAe,EAAE,cAAc;IAC/B,cAAc,EAAE,cAAc;IAC9B,4EAA4E;IAC5E,8EAA8E;IAC9E,aAAa,EAAE,IAAI;IACnB,wDAAwD;IACxD,aAAa,EAAE,IAAI;IACnB,SAAS,EAAE,gBAAgB;IAC3B,UAAU,EAAE,WAAW;IACvB,QAAQ,EAAE,IAAI;CACf,CAAC;AAEF;oEACoE;AACpE,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,OAAO,qBAAqB,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC;AACpD,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export interface AccessDeniedProps {
|
|
3
|
+
/** The missing permission, named for the user (e.g. `audit_log:read`).
|
|
4
|
+
* Omit when unknown (a bare 403). */
|
|
5
|
+
requiredPermission?: string;
|
|
6
|
+
/** Presentation size: `page` (default) for a route-level deny, `inline`
|
|
7
|
+
* for an embedded section. */
|
|
8
|
+
variant?: "page" | "inline";
|
|
9
|
+
/** Override the title. */
|
|
10
|
+
title?: string;
|
|
11
|
+
/** Extra context under the title (defaults to a role-based explanation). */
|
|
12
|
+
description?: ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* When provided, renders a "Request access" button. Resolve the promise to
|
|
15
|
+
* flip the button into a confirmation ("Request sent — an owner will
|
|
16
|
+
* review it."); reject to show a retryable error. Wire it to
|
|
17
|
+
* `fs.rbac.accessRequests.create(...)` or any custom flow.
|
|
18
|
+
*/
|
|
19
|
+
onRequestAccess?: () => Promise<void> | void;
|
|
20
|
+
/** Appended to the root card. */
|
|
21
|
+
className?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A self-contained "you don't have access" card that names the missing
|
|
25
|
+
* permission and (optionally) starts a request-access flow.
|
|
26
|
+
*
|
|
27
|
+
* @example route-level deny under a guard:
|
|
28
|
+
* ```tsx
|
|
29
|
+
* <AccessDenied
|
|
30
|
+
* requiredPermission="audit_log:read"
|
|
31
|
+
* onRequestAccess={() =>
|
|
32
|
+
* fs.rbac.accessRequests.create({ permission: "audit_log:read" })
|
|
33
|
+
* }
|
|
34
|
+
* />
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function AccessDenied({ requiredPermission, variant, title, description, onRequestAccess, className, }: AccessDeniedProps): import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
//# sourceMappingURL=access-denied.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-denied.d.ts","sourceRoot":"","sources":["../../src/components/access-denied.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIjD,MAAM,WAAW,iBAAiB;IAChC;0CACsC;IACtC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;mCAC+B;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC5B,0BAA0B;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC7C,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,EAC3B,kBAAkB,EAClB,OAAgB,EAChB,KAAuC,EACvC,WAAW,EACX,eAAe,EACf,SAAS,GACV,EAAE,iBAAiB,2CAqEnB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
// AccessDenied — the RBAC deny affordance (UA-7). Rendered when a signed-in
|
|
4
|
+
// member lacks a required permission: names EXACTLY what's missing (the
|
|
5
|
+
// unified-grammar `<subject>:<verb>` the edge would also deny) and offers an
|
|
6
|
+
// optional request-access hook. The permission axis never upsells — the
|
|
7
|
+
// viewer's PLAN allows the surface; their ROLE doesn't — so this deliberately
|
|
8
|
+
// has no plan/upgrade wiring (that's <UpgradePrompt> on the entitlement axis).
|
|
9
|
+
//
|
|
10
|
+
// Layout-agnostic (SDK-first tenet): a plain card that drops into any custom
|
|
11
|
+
// frontend — as a <PermissionGate mode="fallback"> node, a route guard's
|
|
12
|
+
// denied render, or a full page body.
|
|
13
|
+
import { useState } from "react";
|
|
14
|
+
import { cx } from "./_internal.js";
|
|
15
|
+
/**
|
|
16
|
+
* A self-contained "you don't have access" card that names the missing
|
|
17
|
+
* permission and (optionally) starts a request-access flow.
|
|
18
|
+
*
|
|
19
|
+
* @example route-level deny under a guard:
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <AccessDenied
|
|
22
|
+
* requiredPermission="audit_log:read"
|
|
23
|
+
* onRequestAccess={() =>
|
|
24
|
+
* fs.rbac.accessRequests.create({ permission: "audit_log:read" })
|
|
25
|
+
* }
|
|
26
|
+
* />
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export function AccessDenied({ requiredPermission, variant = "page", title = "You don't have access to this", description, onRequestAccess, className, }) {
|
|
30
|
+
const [requestState, setRequestState] = useState("idle");
|
|
31
|
+
const body = description ??
|
|
32
|
+
(requiredPermission ? (_jsxs(_Fragment, { children: ["Your role doesn't include the", " ", _jsx("code", { className: "fs-access-denied__permission", children: requiredPermission }), " ", "permission. An organization owner or admin can grant it."] })) : (_jsx(_Fragment, { children: "Your role doesn't allow this. An organization owner or admin can grant access." })));
|
|
33
|
+
const requestAccess = async () => {
|
|
34
|
+
if (!onRequestAccess || requestState === "sending")
|
|
35
|
+
return;
|
|
36
|
+
setRequestState("sending");
|
|
37
|
+
try {
|
|
38
|
+
await onRequestAccess();
|
|
39
|
+
setRequestState("sent");
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
setRequestState("error");
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
return (_jsxs("section", { role: "alert", className: cx("fs-card", "fs-access-denied", variant === "page" && "fs-access-denied--page", className), children: [_jsx("h2", { className: "fs-access-denied__title", children: title }), _jsx("p", { className: "fs-muted fs-access-denied__body", children: body }), onRequestAccess &&
|
|
46
|
+
(requestState === "sent" ? (_jsx("p", { className: "fs-access-denied__sent", children: "Request sent \u2014 an owner will review it." })) : (_jsxs("div", { className: "fs-access-denied__actions", children: [_jsx("button", { type: "button", className: "fs-btn fs-btn--outline fs-btn--sm", onClick: () => void requestAccess(), disabled: requestState === "sending", children: requestState === "sending" ? "Sending…" : "Request access" }), requestState === "error" && (_jsx("span", { className: "fs-access-denied__error", children: "Couldn't send the request \u2014 try again." }))] })))] }));
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=access-denied.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-denied.js","sourceRoot":"","sources":["../../src/components/access-denied.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,4EAA4E;AAC5E,wEAAwE;AACxE,6EAA6E;AAC7E,wEAAwE;AACxE,8EAA8E;AAC9E,+EAA+E;AAC/E,EAAE;AACF,6EAA6E;AAC7E,yEAAyE;AACzE,sCAAsC;AAEtC,OAAO,EAAE,QAAQ,EAAkB,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAwBpC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,YAAY,CAAC,EAC3B,kBAAkB,EAClB,OAAO,GAAG,MAAM,EAChB,KAAK,GAAG,+BAA+B,EACvC,WAAW,EACX,eAAe,EACf,SAAS,GACS;IAClB,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAE9C,MAAM,CAAC,CAAC;IAEV,MAAM,IAAI,GACR,WAAW;QACX,CAAC,kBAAkB,CAAC,CAAC,CAAC,CACpB,+DACgC,GAAG,EACjC,eAAM,SAAS,EAAC,8BAA8B,YAC3C,kBAAkB,GACd,EAAC,GAAG,gEAEV,CACJ,CAAC,CAAC,CAAC,CACF,+GAGG,CACJ,CAAC,CAAC;IAEL,MAAM,aAAa,GAAG,KAAK,IAAI,EAAE;QAC/B,IAAI,CAAC,eAAe,IAAI,YAAY,KAAK,SAAS;YAAE,OAAO;QAC3D,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,eAAe,EAAE,CAAC;YACxB,eAAe,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,eAAe,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,mBACE,IAAI,EAAC,OAAO,EACZ,SAAS,EAAE,EAAE,CACX,SAAS,EACT,kBAAkB,EAClB,OAAO,KAAK,MAAM,IAAI,wBAAwB,EAC9C,SAAS,CACV,aAED,aAAI,SAAS,EAAC,yBAAyB,YAAE,KAAK,GAAM,EACpD,YAAG,SAAS,EAAC,iCAAiC,YAAE,IAAI,GAAK,EACxD,eAAe;gBACd,CAAC,YAAY,KAAK,MAAM,CAAC,CAAC,CAAC,CACzB,YAAG,SAAS,EAAC,wBAAwB,6DAEjC,CACL,CAAC,CAAC,CAAC,CACF,eAAK,SAAS,EAAC,2BAA2B,aACxC,iBACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,mCAAmC,EAC7C,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,aAAa,EAAE,EACnC,QAAQ,EAAE,YAAY,KAAK,SAAS,YAEnC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,gBAAgB,GACpD,EACR,YAAY,KAAK,OAAO,IAAI,CAC3B,eAAM,SAAS,EAAC,yBAAyB,4DAElC,CACR,IACG,CACP,CAAC,IACI,CACX,CAAC;AACJ,CAAC"}
|
|
@@ -2,8 +2,10 @@ import { type ReactNode } from "react";
|
|
|
2
2
|
import type { AuthStrategy } from "../types.js";
|
|
3
3
|
/** The guard's resolved decision. `redirecting` carries the target the host
|
|
4
4
|
* should navigate to; `allowed` reveals the protected subtree; `loading`
|
|
5
|
-
* holds (no flash) until the auth layer settles
|
|
6
|
-
|
|
5
|
+
* holds (no flash) until the auth layer settles; `denied` means the user is
|
|
6
|
+
* signed in but lacks a required Managed-RBAC permission (FAR-700) — render
|
|
7
|
+
* the fallback, don't redirect. */
|
|
8
|
+
export type AuthGuardStatus = "loading" | "allowed" | "redirecting" | "denied";
|
|
7
9
|
export interface AuthGuardDecision {
|
|
8
10
|
status: AuthGuardStatus;
|
|
9
11
|
/** Present only when `status === "redirecting"` — where the host should go. */
|
|
@@ -19,13 +21,27 @@ export interface AuthGuardInput {
|
|
|
19
21
|
/** Where to send a signed-out user off an auth-required surface. Defaults to
|
|
20
22
|
* "/" (the public landing — the dev-portal-template convention). */
|
|
21
23
|
redirectTo?: string;
|
|
24
|
+
/** A Managed-RBAC permission the surface additionally requires (FAR-700),
|
|
25
|
+
* in the `<feature>:read|write` grammar. Checked via {@link hasPermission}
|
|
26
|
+
* AFTER the sign-in gate; a signed-in user lacking it → `denied`.
|
|
27
|
+
*
|
|
28
|
+
* ⚠️ UX ONLY: this hides UI, but the gateway's `permission` constraint is
|
|
29
|
+
* the security boundary — a call the user isn't permitted to make is
|
|
30
|
+
* denied at the edge regardless of what the client renders. */
|
|
31
|
+
requirePermission?: string;
|
|
32
|
+
/** The permission check (normally `useFsAuth().hasPermission`). Required
|
|
33
|
+
* for `requirePermission` to have any effect; returns false while the
|
|
34
|
+
* server-resolved permissions are still loading, so the guard denies
|
|
35
|
+
* first and reveals once they arrive. */
|
|
36
|
+
hasPermission?: (key: string) => boolean;
|
|
22
37
|
}
|
|
23
38
|
/**
|
|
24
39
|
* The pure auth-guard decision (no React, no router). While auth is loading →
|
|
25
40
|
* `loading`. Once loaded: a public surface (`requireAuth: false`) is always
|
|
26
41
|
* `allowed`; an auth-required surface is `allowed` for a signed-in user and
|
|
27
|
-
* `redirecting` (to `redirectTo` ?? "/") for a signed-out one.
|
|
28
|
-
*
|
|
42
|
+
* `redirecting` (to `redirectTo` ?? "/") for a signed-out one. A signed-in
|
|
43
|
+
* user missing `requirePermission` → `denied` (fallback, no redirect).
|
|
44
|
+
* Exported for direct use + unit testing; `useAuthGuard` is the React wrapper.
|
|
29
45
|
*/
|
|
30
46
|
export declare function planAuthGuard(input: AuthGuardInput): AuthGuardDecision;
|
|
31
47
|
export interface UseAuthGuardOptions {
|
|
@@ -33,6 +49,11 @@ export interface UseAuthGuardOptions {
|
|
|
33
49
|
requireAuth: boolean;
|
|
34
50
|
/** Where to send a signed-out user. Defaults to "/". */
|
|
35
51
|
redirectTo?: string;
|
|
52
|
+
/** A Managed-RBAC permission the surface additionally requires (FAR-700).
|
|
53
|
+
* Checked via the managed `useFsAuth().hasPermission` — a signed-in user
|
|
54
|
+
* lacking it resolves `denied` (fallback, no redirect). UX only; the edge
|
|
55
|
+
* `permission` constraint is the security boundary. */
|
|
56
|
+
requirePermission?: string;
|
|
36
57
|
/** sessionStorage key under which the current location is stashed before a
|
|
37
58
|
* redirect, so the host can restore the deep link after sign-in. When set
|
|
38
59
|
* (and in a browser), the guard writes `location.pathname + search` on a
|
|
@@ -56,10 +77,18 @@ export declare function useAuthGuard(opts: UseAuthGuardOptions): AuthGuardDecisi
|
|
|
56
77
|
export declare function resolveSignInDestination(strategy: AuthStrategy): string | null;
|
|
57
78
|
export interface RequireAuthProps {
|
|
58
79
|
children?: ReactNode;
|
|
59
|
-
/** Rendered while loading
|
|
60
|
-
*
|
|
61
|
-
* there's no
|
|
80
|
+
/** Rendered while loading, while redirecting (signed-out), or when a
|
|
81
|
+
* `requirePermission` check denies. Defaults to an aria-busy placeholder
|
|
82
|
+
* so assistive tech announces the pending state and there's no
|
|
83
|
+
* flash-of-protected-content. */
|
|
62
84
|
fallback?: ReactNode;
|
|
85
|
+
/** A Managed-RBAC permission (`<feature>:read|write`) the subtree
|
|
86
|
+
* additionally requires (FAR-700). A signed-in user lacking it gets the
|
|
87
|
+
* `fallback` (no redirect). Composes with the existing props: the
|
|
88
|
+
* sign-in gate still runs first. UX ONLY — the gateway's `permission`
|
|
89
|
+
* constraint is the security boundary, so a hidden control is a
|
|
90
|
+
* convenience, never a defense. */
|
|
91
|
+
requirePermission?: string;
|
|
63
92
|
/** Where a signed-out user should go. Surfaced on the decision so a host
|
|
64
93
|
* effect can navigate; `<RequireAuth>` itself never navigates. Defaults
|
|
65
94
|
* to "/". */
|
|
@@ -71,10 +100,13 @@ export interface RequireAuthProps {
|
|
|
71
100
|
onRedirect?: (redirectTo: string) => void;
|
|
72
101
|
}
|
|
73
102
|
/**
|
|
74
|
-
* Reveal `children` only when the user is signed in
|
|
75
|
-
* `
|
|
76
|
-
* `
|
|
77
|
-
*
|
|
103
|
+
* Reveal `children` only when the user is signed in (and, when
|
|
104
|
+
* `requirePermission` is set, holds that Managed-RBAC permission). While auth
|
|
105
|
+
* loads → `fallback` (aria-busy by default, no flash); signed-out →
|
|
106
|
+
* `fallback` and, if `onRedirect` is supplied, a call with the redirect
|
|
107
|
+
* target (the host navigates); permission-denied → `fallback` only (no
|
|
108
|
+
* redirect — the user is signed in, just under-permissioned). Self-managed
|
|
109
|
+
* under `<FartherShoreRoot>`.
|
|
78
110
|
*/
|
|
79
|
-
export declare function RequireAuth({ children, fallback, redirectTo, onRedirect, }: RequireAuthProps): import("react/jsx-runtime").JSX.Element;
|
|
111
|
+
export declare function RequireAuth({ children, fallback, requirePermission, redirectTo, onRedirect, }: RequireAuthProps): import("react/jsx-runtime").JSX.Element;
|
|
80
112
|
//# sourceMappingURL=auth-guard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-guard.d.ts","sourceRoot":"","sources":["../../src/components/auth-guard.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD
|
|
1
|
+
{"version":3,"file":"auth-guard.d.ts","sourceRoot":"","sources":["../../src/components/auth-guard.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD;;;;oCAIoC;AACpC,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,GAAG,QAAQ,CAAC;AAE/E,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,eAAe,CAAC;IACxB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,MAAM,EAAE,OAAO,CAAC;IAChB,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAC;IAClB,yDAAyD;IACzD,WAAW,EAAE,OAAO,CAAC;IACrB;yEACqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;oEAMgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;8CAG0C;IAC1C,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;CAC1C;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,iBAAiB,CAatE;AAED,MAAM,WAAW,mBAAmB;IAClC,2DAA2D;IAC3D,WAAW,EAAE,OAAO,CAAC;IACrB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;4DAGwD;IACxD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;oFAGgF;IAChF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAID;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,iBAAiB,CA6BzE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,YAAY,GACrB,MAAM,GAAG,IAAI,CAEf;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;sCAGkC;IAClC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;;wCAKoC;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;kBAEc;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;0BAGsB;IACtB,UAAU,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C;AAUD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,QAAQ,EACR,iBAAiB,EACjB,UAAU,EACV,UAAU,GACX,EAAE,gBAAgB,2CAiBlB"}
|
|
@@ -13,17 +13,23 @@ import { useFsAuth } from "./auth.js";
|
|
|
13
13
|
* The pure auth-guard decision (no React, no router). While auth is loading →
|
|
14
14
|
* `loading`. Once loaded: a public surface (`requireAuth: false`) is always
|
|
15
15
|
* `allowed`; an auth-required surface is `allowed` for a signed-in user and
|
|
16
|
-
* `redirecting` (to `redirectTo` ?? "/") for a signed-out one.
|
|
17
|
-
*
|
|
16
|
+
* `redirecting` (to `redirectTo` ?? "/") for a signed-out one. A signed-in
|
|
17
|
+
* user missing `requirePermission` → `denied` (fallback, no redirect).
|
|
18
|
+
* Exported for direct use + unit testing; `useAuthGuard` is the React wrapper.
|
|
18
19
|
*/
|
|
19
20
|
export function planAuthGuard(input) {
|
|
20
21
|
if (!input.loaded)
|
|
21
22
|
return { status: "loading" };
|
|
22
23
|
if (!input.requireAuth)
|
|
23
24
|
return { status: "allowed" };
|
|
24
|
-
if (input.signedIn)
|
|
25
|
-
return { status: "
|
|
26
|
-
|
|
25
|
+
if (!input.signedIn) {
|
|
26
|
+
return { status: "redirecting", redirectTo: input.redirectTo ?? "/" };
|
|
27
|
+
}
|
|
28
|
+
if (input.requirePermission !== undefined &&
|
|
29
|
+
!(input.hasPermission?.(input.requirePermission) ?? false)) {
|
|
30
|
+
return { status: "denied" };
|
|
31
|
+
}
|
|
32
|
+
return { status: "allowed" };
|
|
27
33
|
}
|
|
28
34
|
const DEFAULT_RETURN_TO_KEY = "fs-return-to";
|
|
29
35
|
/**
|
|
@@ -40,6 +46,8 @@ export function useAuthGuard(opts) {
|
|
|
40
46
|
signedIn: auth.signedIn,
|
|
41
47
|
requireAuth: opts.requireAuth,
|
|
42
48
|
redirectTo: opts.redirectTo,
|
|
49
|
+
requirePermission: opts.requirePermission,
|
|
50
|
+
hasPermission: auth.hasPermission,
|
|
43
51
|
});
|
|
44
52
|
const returnToKey = opts.returnToKey === undefined ? DEFAULT_RETURN_TO_KEY : opts.returnToKey;
|
|
45
53
|
useEffect(() => {
|
|
@@ -73,13 +81,20 @@ function AuthPending() {
|
|
|
73
81
|
return (_jsx("span", { "aria-busy": "true", "aria-live": "polite", style: { display: "contents" } }));
|
|
74
82
|
}
|
|
75
83
|
/**
|
|
76
|
-
* Reveal `children` only when the user is signed in
|
|
77
|
-
* `
|
|
78
|
-
* `
|
|
79
|
-
*
|
|
84
|
+
* Reveal `children` only when the user is signed in (and, when
|
|
85
|
+
* `requirePermission` is set, holds that Managed-RBAC permission). While auth
|
|
86
|
+
* loads → `fallback` (aria-busy by default, no flash); signed-out →
|
|
87
|
+
* `fallback` and, if `onRedirect` is supplied, a call with the redirect
|
|
88
|
+
* target (the host navigates); permission-denied → `fallback` only (no
|
|
89
|
+
* redirect — the user is signed in, just under-permissioned). Self-managed
|
|
90
|
+
* under `<FartherShoreRoot>`.
|
|
80
91
|
*/
|
|
81
|
-
export function RequireAuth({ children, fallback, redirectTo, onRedirect, }) {
|
|
82
|
-
const decision = useAuthGuard({
|
|
92
|
+
export function RequireAuth({ children, fallback, requirePermission, redirectTo, onRedirect, }) {
|
|
93
|
+
const decision = useAuthGuard({
|
|
94
|
+
requireAuth: true,
|
|
95
|
+
redirectTo,
|
|
96
|
+
requirePermission,
|
|
97
|
+
});
|
|
83
98
|
useEffect(() => {
|
|
84
99
|
if (decision.status === "redirecting" && decision.redirectTo) {
|
|
85
100
|
onRedirect?.(decision.redirectTo);
|
|
@@ -87,7 +102,8 @@ export function RequireAuth({ children, fallback, redirectTo, onRedirect, }) {
|
|
|
87
102
|
}, [decision.status, decision.redirectTo, onRedirect]);
|
|
88
103
|
if (decision.status === "allowed")
|
|
89
104
|
return _jsx(_Fragment, { children: children });
|
|
90
|
-
// loading OR
|
|
105
|
+
// loading, redirecting, OR permission-denied → the fallback (default:
|
|
106
|
+
// aria-busy placeholder).
|
|
91
107
|
return _jsx(_Fragment, { children: fallback ?? _jsx(AuthPending, {}) });
|
|
92
108
|
}
|
|
93
109
|
//# sourceMappingURL=auth-guard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-guard.js","sourceRoot":"","sources":["../../src/components/auth-guard.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,+DAA+D;AAC/D,gFAAgF;AAChF,0EAA0E;AAC1E,8EAA8E;AAC9E,yEAAyE;AACzE,EAAE;AACF,8CAA8C;AAE9C,OAAO,EAAE,SAAS,EAAkB,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"auth-guard.js","sourceRoot":"","sources":["../../src/components/auth-guard.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,+DAA+D;AAC/D,gFAAgF;AAChF,0EAA0E;AAC1E,8EAA8E;AAC9E,yEAAyE;AACzE,EAAE;AACF,8CAA8C;AAE9C,OAAO,EAAE,SAAS,EAAkB,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAwCtC;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,KAAqB;IACjD,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IAChD,IAAI,CAAC,KAAK,CAAC,WAAW;QAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACrD,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;IACxE,CAAC;IACD,IACE,KAAK,CAAC,iBAAiB,KAAK,SAAS;QACrC,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,KAAK,CAAC,EAC1D,CAAC;QACD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC/B,CAAC;AAmBD,MAAM,qBAAqB,GAAG,cAAc,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,IAAyB;IACpD,MAAM,IAAI,GAAG,SAAS,EAAE,CAAC;IACzB,MAAM,QAAQ,GAAG,aAAa,CAAC;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,aAAa,EAAE,IAAI,CAAC,aAAa;KAClC,CAAC,CAAC;IAEH,MAAM,WAAW,GACf,IAAI,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;IAE5E,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,QAAQ,CAAC,MAAM,KAAK,aAAa;YAAE,OAAO;QAC9C,IAAI,CAAC,WAAW;YAAE,OAAO;QACzB,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAC1C,IAAI,CAAC;YACH,MAAM,CAAC,cAAc,CAAC,OAAO,CAC3B,WAAW,EACX,MAAM,CAAC,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAClD,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,yDAAyD;QAC3D,CAAC;IACH,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAEnC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAsB;IAEtB,OAAO,QAAQ,KAAK,eAAe,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC;AAClE,CAAC;AA2BD;kFACkF;AAClF,SAAS,WAAW;IAClB,OAAO,CACL,4BAAgB,MAAM,eAAW,QAAQ,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,GAAI,CAC7E,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,QAAQ,EACR,QAAQ,EACR,iBAAiB,EACjB,UAAU,EACV,UAAU,GACO;IACjB,MAAM,QAAQ,GAAG,YAAY,CAAC;QAC5B,WAAW,EAAE,IAAI;QACjB,UAAU;QACV,iBAAiB;KAClB,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,QAAQ,CAAC,MAAM,KAAK,aAAa,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YAC7D,UAAU,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;IAEvD,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,4BAAG,QAAQ,GAAI,CAAC;IAC1D,sEAAsE;IACtE,0BAA0B;IAC1B,OAAO,4BAAG,QAAQ,IAAI,KAAC,WAAW,KAAG,GAAI,CAAC;AAC5C,CAAC"}
|
|
@@ -26,6 +26,33 @@ export interface FsAuth {
|
|
|
26
26
|
user: FsAuthUser | null;
|
|
27
27
|
/** Re-read the session (persona only; Clerk pushes its own state). */
|
|
28
28
|
refresh(): void;
|
|
29
|
+
/** Managed-RBAC product-role keys assigned to the signed-in user
|
|
30
|
+
* (FAR-700), server-resolved from `GET /me` — the SDK never decodes
|
|
31
|
+
* tokens client-side. `[]` while auth/permissions load and when signed
|
|
32
|
+
* out. */
|
|
33
|
+
roles: string[];
|
|
34
|
+
/** The user's resolved permission strings (`<feature>:read|write`
|
|
35
|
+
* grammar). Personal orgs / RBAC-off products resolve to `["*"]` (full
|
|
36
|
+
* access). `[]` while loading / signed out. */
|
|
37
|
+
permissions: string[];
|
|
38
|
+
/**
|
|
39
|
+
* Whether the signed-in user's permissions grant `key` under the unified
|
|
40
|
+
* grammar (`*` / `<subject>:*` / exact — no verb-class widening). Returns
|
|
41
|
+
* `false` while permissions load and when signed out.
|
|
42
|
+
*
|
|
43
|
+
* ⚠️ UX ONLY — hide affordances with it, but the gateway's `permission`
|
|
44
|
+
* constraint is the security boundary: a request the user isn't permitted
|
|
45
|
+
* to make is denied at the edge regardless of what the client renders.
|
|
46
|
+
*/
|
|
47
|
+
hasPermission(key: string): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* True once the Managed-RBAC claim has settled: the `/me` read answered
|
|
50
|
+
* (or failed → deny-defaults locked in), or the viewer is signed out /
|
|
51
|
+
* auth finished loading without a session. While false, permission-gated
|
|
52
|
+
* UI should render a pending placeholder instead of flashing a deny —
|
|
53
|
+
* `usePermissionGate` consumes this so `<PermissionGate>` never flickers.
|
|
54
|
+
*/
|
|
55
|
+
authzLoaded: boolean;
|
|
29
56
|
}
|
|
30
57
|
export declare function useFsAuth(): FsAuth;
|
|
31
58
|
/** Like {@link useFsAuth} but null outside the managed auth layer — lets
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/components/auth.tsx"],"names":[],"mappings":"AAsBA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/components/auth.tsx"],"names":[],"mappings":"AAsBA,OAAO,EAQL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAU5D;;;+EAG+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,YAAY,CAAC;IACvB,gFAAgF;IAChF,MAAM,EAAE,OAAO,CAAC;IAChB;iFAC6E;IAC7E,kBAAkB,EAAE,OAAO,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB;qFACiF;IACjF,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB;mCAC+B;IAC/B,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACxB,sEAAsE;IACtE,OAAO,IAAI,IAAI,CAAC;IAChB;;;eAGW;IACX,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;oDAEgD;IAChD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;;;;;;;;OAQG;IACH,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACpC;;;;;;OAMG;IACH,WAAW,EAAE,OAAO,CAAC;CACtB;AAiBD,wBAAgB,SAAS,IAAI,MAAM,CAQlC;AAED;0EAC0E;AAC1E,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CAEjD;AAID,sDAAsD;AACtD,wBAAgB,QAAQ,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,kDAG7D;AAED;oCACoC;AACpC,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,kDAG9D;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,kDAGhE;AAED;;mEAEmE;AACnE,wBAAgB,cAAc,CAAC,EAC7B,SAA2C,EAC3C,QAAoB,GACrB,EAAE;IACD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,2CAOA;AAED,gDAAgD;AAChD,wBAAgB,eAAe,CAAC,EAC9B,SAA+C,EAC/C,QAAqB,GACtB,EAAE;IACD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,2CAWA;AAqZD;;;+CAG+C;AAC/C,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,aAAa,GAAG,SAAS,GAClC,aAAa,GAAG,SAAS,CAS3B;AAmFD;iFACiF;AACjF,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,KAAK,EACL,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,SAAS,CAAC;CACrB,2CAgBA;AAID;;0EAE0E;AAC1E,wBAAgB,YAAY,mDA6B3B"}
|