@ethisyscore/extension-runtime 1.30.0 → 1.31.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.
@@ -623,4 +623,47 @@ interface UseFrontendSessionTokenResult {
623
623
  */
624
624
  declare function useFrontendSessionToken(transport: McpTransport): UseFrontendSessionTokenResult;
625
625
 
626
- export { BridgeClientContext, type ClientPushChannel, ClientPushContext, type ClientPushEvent, type ClientPushSubscribeOptions, type CreatePortMcpTransportOptions, type CreateRemoteRootOptions, type DeclarativePluginConfig, type EthisysPluginConfig, ExtensionRuntimeProvider, type ExtensionRuntimeProviderProps, type HostIdentity, HostIdentityContext, type HostIdentityUser, type HostPermission, type ItemsResponse, LocalePayload, McpTransport, PluginRealtimeContext, type PluginRealtimeSource, PortBridgeClient, type PortShim, type RemoteRoot, ThemePayload, type UseClientPushSubscriptionOptions, type UseFrontendSessionTokenResult, type UseMcpQueryOptions, type UseMcpQueryResult, type UseMcpResourceOptions, type UseMcpResourceResult, type UseMcpToolOptions, type UseMcpToolResult, createPortMcpTransport, createRemoteRoot, defineDeclarativePlugin, defineEthisysPlugin, unwrapItems, useBridgeClient, useBridgeLocale, useBridgeTheme, useClientPushSubscription, useFrontendSessionToken, useHostIdentity, useMcpQuery, useMcpResource, useMcpTool, usePluginRealtimeSource };
626
+ /**
627
+ * Pure JWT-payload decode helper (WI 5160 — F-AUTH-SEAM FE face).
628
+ *
629
+ * Extracts and JSON-parses the middle (payload) segment of a compact JWT.
630
+ * URL-safe base64url characters (`-` → `+`, `_` → `/`) are normalised and
631
+ * missing `=` padding is restored before passing to `atob`.
632
+ *
633
+ * This helper is intentionally side-effect-free and React-free so it can be
634
+ * unit-tested without a DOM environment.
635
+ *
636
+ * **Security note:** this function does NOT validate the JWT signature —
637
+ * the host already validated the token at mint time. The FE only reads claims.
638
+ *
639
+ * @param token A compact-serialised JWT (`header.payload.signature`) or null.
640
+ * @returns The parsed payload object, or `{}` if the token is absent, malformed,
641
+ * has fewer than 3 segments, or the payload is not valid JSON.
642
+ */
643
+ declare function decodeJwtPayload(token: string | null): Record<string, unknown>;
644
+
645
+ interface UseAuthResult {
646
+ /** The caller's user ID from the FE-session JWT, or null while loading / on error. */
647
+ currentUserId: string | null;
648
+ /**
649
+ * Returns true if the caller has the given short-code permission.
650
+ * Always returns false while the token is loading or absent (fail-closed).
651
+ *
652
+ * @param shortCode The exact permission short code, e.g. `"timeslip.read"`.
653
+ */
654
+ hasPermission(shortCode: string): boolean;
655
+ /** True while the first fetch (or a silent refresh) is in-flight. */
656
+ isLoading: boolean;
657
+ /** Set when the bridge rejects; null otherwise. */
658
+ error: Error | null;
659
+ }
660
+ /**
661
+ * Returns the caller's identity and permission gate derived from the
662
+ * FE-session token.
663
+ *
664
+ * @param transport The {@link McpTransport} to use. Typically the context
665
+ * transport from the extension runtime provider.
666
+ */
667
+ declare function useAuth(transport: McpTransport): UseAuthResult;
668
+
669
+ export { BridgeClientContext, type ClientPushChannel, ClientPushContext, type ClientPushEvent, type ClientPushSubscribeOptions, type CreatePortMcpTransportOptions, type CreateRemoteRootOptions, type DeclarativePluginConfig, type EthisysPluginConfig, ExtensionRuntimeProvider, type ExtensionRuntimeProviderProps, type HostIdentity, HostIdentityContext, type HostIdentityUser, type HostPermission, type ItemsResponse, LocalePayload, McpTransport, PluginRealtimeContext, type PluginRealtimeSource, PortBridgeClient, type PortShim, type RemoteRoot, ThemePayload, type UseAuthResult, type UseClientPushSubscriptionOptions, type UseFrontendSessionTokenResult, type UseMcpQueryOptions, type UseMcpQueryResult, type UseMcpResourceOptions, type UseMcpResourceResult, type UseMcpToolOptions, type UseMcpToolResult, createPortMcpTransport, createRemoteRoot, decodeJwtPayload, defineDeclarativePlugin, defineEthisysPlugin, unwrapItems, useAuth, useBridgeClient, useBridgeLocale, useBridgeTheme, useClientPushSubscription, useFrontendSessionToken, useHostIdentity, useMcpQuery, useMcpResource, useMcpTool, usePluginRealtimeSource };
@@ -751,6 +751,46 @@ function useFrontendSessionToken(transport) {
751
751
  return { token, isLoading, error };
752
752
  }
753
753
 
754
- export { BridgeClientContext, ClientPushContext, ExtensionRuntimeProvider, HostIdentityContext, PluginRealtimeContext, createPortBridgeClient, createPortMcpTransport, createRemoteRoot, defineDeclarativePlugin, defineEthisysPlugin, unwrapItems, useBridgeClient, useBridgeLocale, useBridgeTheme, useClientPushSubscription, useFrontendSessionToken, useHostIdentity, useMcpQuery, useMcpResource, useMcpTool, usePluginRealtimeSource };
754
+ // src/plugin/decodeJwtPayload.ts
755
+ function decodeJwtPayload(token) {
756
+ if (token === null || token === "") {
757
+ return {};
758
+ }
759
+ const segments = token.split(".");
760
+ if (segments.length < 3) {
761
+ return {};
762
+ }
763
+ const payloadSegment = segments[1];
764
+ try {
765
+ const base64 = payloadSegment.replace(/-/g, "+").replace(/_/g, "/");
766
+ const padded = base64 + "===".slice(0, (4 - base64.length % 4) % 4);
767
+ const json = atob(padded);
768
+ const parsed = JSON.parse(json);
769
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
770
+ return {};
771
+ }
772
+ return parsed;
773
+ } catch {
774
+ return {};
775
+ }
776
+ }
777
+ function useAuth(transport) {
778
+ const { token, isLoading, error } = useFrontendSessionToken(transport);
779
+ const { currentUserId, permissionSet } = useMemo(() => {
780
+ const claims = decodeJwtPayload(token);
781
+ const userId = (typeof claims["user_id"] === "string" && claims["user_id"] !== "" ? claims["user_id"] : null) ?? (typeof claims["sub"] === "string" && claims["sub"] !== "" ? claims["sub"] : null);
782
+ const permissionsRaw = typeof claims["permissions"] === "string" ? claims["permissions"] : "";
783
+ const set = permissionsRaw.length > 0 ? new Set(permissionsRaw.split(" ").filter((s) => s.length > 0)) : /* @__PURE__ */ new Set();
784
+ return { currentUserId: userId, permissionSet: set };
785
+ }, [token]);
786
+ return {
787
+ currentUserId,
788
+ hasPermission: (shortCode) => permissionSet.has(shortCode),
789
+ isLoading,
790
+ error
791
+ };
792
+ }
793
+
794
+ export { BridgeClientContext, ClientPushContext, ExtensionRuntimeProvider, HostIdentityContext, PluginRealtimeContext, createPortBridgeClient, createPortMcpTransport, createRemoteRoot, decodeJwtPayload, defineDeclarativePlugin, defineEthisysPlugin, unwrapItems, useAuth, useBridgeClient, useBridgeLocale, useBridgeTheme, useClientPushSubscription, useFrontendSessionToken, useHostIdentity, useMcpQuery, useMcpResource, useMcpTool, usePluginRealtimeSource };
755
795
  //# sourceMappingURL=index.js.map
756
796
  //# sourceMappingURL=index.js.map