@vertesia/ui 1.6.0-dev.20261014.015055Z → 1.6.0-dev.20261022.120426Z
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/lib/core/components/shadcn/selectBox.js +1 -1
- package/lib/core/components/shadcn/selectBox.js.map +1 -1
- package/lib/features/agent/PayloadBuilder.d.ts +1 -1
- package/lib/features/oauth/useMcpConnections.d.ts.map +1 -1
- package/lib/features/oauth/useMcpConnections.js +21 -8
- package/lib/features/oauth/useMcpConnections.js.map +1 -1
- package/lib/features/store/objects/DocumentTable.d.ts.map +1 -1
- package/lib/features/store/objects/DocumentTable.js +0 -9
- package/lib/features/store/objects/DocumentTable.js.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.d.ts.map +1 -1
- package/lib/features/store/objects/components/ContentOverview.js +2 -30
- package/lib/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/features/store/objects/components/VectorSearchWidget.d.ts.map +1 -1
- package/lib/features/store/objects/components/VectorSearchWidget.js +1 -1
- package/lib/features/store/objects/components/VectorSearchWidget.js.map +1 -1
- package/lib/features/store/objects/components/textPanelSource.d.ts +14 -0
- package/lib/features/store/objects/components/textPanelSource.d.ts.map +1 -0
- package/lib/features/store/objects/components/textPanelSource.js +52 -0
- package/lib/features/store/objects/components/textPanelSource.js.map +1 -0
- package/lib/features/store/objects/upload/DocumentUploadModal.d.ts.map +1 -1
- package/lib/features/store/objects/upload/DocumentUploadModal.js +13 -9
- package/lib/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
- package/lib/session/auth/oauth.d.ts.map +1 -1
- package/lib/session/auth/oauth.js +18 -10
- package/lib/session/auth/oauth.js.map +1 -1
- package/lib/vertesia-ui-boot.js.map +1 -1
- package/lib/vertesia-ui-core.js +76 -76
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-env.js.map +1 -1
- package/lib/vertesia-ui-features.js +339 -339
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-i18n.js +1 -1
- package/lib/vertesia-ui-i18n.js.map +1 -1
- package/lib/vertesia-ui-layout.js +16 -16
- package/lib/vertesia-ui-layout.js.map +1 -1
- package/lib/vertesia-ui-rich-text.js +118 -118
- package/lib/vertesia-ui-rich-text.js.map +1 -1
- package/lib/vertesia-ui-router.js +1 -1
- package/lib/vertesia-ui-router.js.map +1 -1
- package/lib/vertesia-ui-session.js +1 -1
- package/lib/vertesia-ui-session.js.map +1 -1
- package/lib/vertesia-ui-shell.js +26 -26
- package/lib/vertesia-ui-shell.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +148 -148
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/lib/widgets/markdown/MermaidDiagram.d.ts.map +1 -1
- package/lib/widgets/markdown/MermaidDiagram.js +5 -2
- package/lib/widgets/markdown/MermaidDiagram.js.map +1 -1
- package/lib/widgets/upload/DropZone.d.ts.map +1 -1
- package/lib/widgets/upload/DropZone.js +1 -0
- package/lib/widgets/upload/DropZone.js.map +1 -1
- package/package.json +46 -41
- package/src/core/components/shadcn/selectBox.tsx +1 -1
- package/src/features/oauth/useMcpConnections.ts +26 -8
- package/src/features/store/objects/DocumentTable.tsx +0 -9
- package/src/features/store/objects/components/ContentOverview.tsx +2 -34
- package/src/features/store/objects/components/VectorSearchWidget.tsx +4 -2
- package/src/features/store/objects/components/textPanelSource.ts +58 -0
- package/src/features/store/objects/upload/DocumentUploadModal.tsx +14 -10
- package/src/session/auth/oauth.ts +18 -9
- package/src/widgets/markdown/MermaidDiagram.tsx +5 -2
- package/src/widgets/upload/DropZone.tsx +1 -0
|
@@ -6,6 +6,7 @@ import { markCentralAuthRoundTripStarted } from './authRoundTrip';
|
|
|
6
6
|
import { verifyAuthState } from './authState';
|
|
7
7
|
import { usesGatewaySession } from './gateway';
|
|
8
8
|
import { isStsTokenIssuer } from './tokenIssuer';
|
|
9
|
+
import { isLoopbackHostname } from './vertesiaHosts';
|
|
9
10
|
|
|
10
11
|
const TRANSACTION_KEY = 'vertesia.oauth.transaction';
|
|
11
12
|
const TOKEN_KEY = 'vertesia.oauth.access';
|
|
@@ -55,9 +56,13 @@ function base64url(bytes: Uint8Array): string {
|
|
|
55
56
|
function randomValue(): string {
|
|
56
57
|
return base64url(crypto.getRandomValues(new Uint8Array(32)));
|
|
57
58
|
}
|
|
58
|
-
|
|
59
|
+
/** Validate a public protocol endpoint URL. The returned URL is routing metadata, not a credential. */
|
|
60
|
+
function validatedEndpointUrl(value: string): URL {
|
|
59
61
|
const url = new URL(value);
|
|
60
|
-
|
|
62
|
+
const localHttp = Env.isLocalDev && url.protocol === 'http:' && isLoopbackHostname(url.hostname);
|
|
63
|
+
if ((url.protocol !== 'https:' && !localHttp) || url.username || url.password) {
|
|
64
|
+
throw new Error('OAuth endpoint must use HTTPS or local-development loopback HTTP');
|
|
65
|
+
}
|
|
61
66
|
return url;
|
|
62
67
|
}
|
|
63
68
|
|
|
@@ -97,11 +102,13 @@ async function acquireToken(forceRefresh = false): Promise<string> {
|
|
|
97
102
|
}
|
|
98
103
|
const redirectUri = redirect.toString();
|
|
99
104
|
if (new URL(redirectUri).origin !== window.location.origin) throw new Error('OAuth callback must be same-origin');
|
|
100
|
-
const issuer = (config.issuer
|
|
105
|
+
const issuer = validatedEndpointUrl(config.issuer ?? Env.endpoints.sts)
|
|
106
|
+
.toString()
|
|
107
|
+
.replace(/\/+$/, '');
|
|
101
108
|
// A token is issued for one audience. The default audience follows the issuer, which is already part of every
|
|
102
109
|
// stored credential's identity; a configured one is recorded alongside it, so changing it never reuses a token,
|
|
103
110
|
// refresh session or login transaction issued for the previous audience.
|
|
104
|
-
const configuredResource = config.resource ?
|
|
111
|
+
const configuredResource = config.resource ? validatedEndpointUrl(config.resource).toString() : undefined;
|
|
105
112
|
const sameClient = (stored: { clientId: string; issuer: string; resource?: string }) =>
|
|
106
113
|
stored.clientId === clientId && stored.issuer === issuer && stored.resource === configuredResource;
|
|
107
114
|
let current = new URL(window.location.href);
|
|
@@ -184,10 +191,12 @@ async function acquireToken(forceRefresh = false): Promise<string> {
|
|
|
184
191
|
revocation_endpoint?: string;
|
|
185
192
|
} = await discovery.json();
|
|
186
193
|
if (metadata.issuer.replace(/\/+$/, '') !== issuer) throw new Error('OAuth issuer mismatch');
|
|
187
|
-
const authorize =
|
|
188
|
-
const tokenEndpoint =
|
|
194
|
+
const authorize = validatedEndpointUrl(metadata.authorization_endpoint);
|
|
195
|
+
const tokenEndpoint = validatedEndpointUrl(metadata.token_endpoint);
|
|
189
196
|
const revocationEndpoint =
|
|
190
|
-
metadata.revocation_endpoint === undefined
|
|
197
|
+
metadata.revocation_endpoint === undefined
|
|
198
|
+
? undefined
|
|
199
|
+
: validatedEndpointUrl(metadata.revocation_endpoint).toString();
|
|
191
200
|
const resource = configuredResource ?? new URL(metadata.issuer).toString();
|
|
192
201
|
if (refreshCredential) {
|
|
193
202
|
try {
|
|
@@ -299,7 +308,7 @@ async function acquireToken(forceRefresh = false): Promise<string> {
|
|
|
299
308
|
}
|
|
300
309
|
let scopes = config.scopes ?? ['openid', 'profile'];
|
|
301
310
|
if (clientId.startsWith('https://')) {
|
|
302
|
-
const documentResponse = await fetch(
|
|
311
|
+
const documentResponse = await fetch(validatedEndpointUrl(clientId), { cache: 'no-store' });
|
|
303
312
|
if (!documentResponse.ok) throw new Error(`Application CIMD unavailable (${documentResponse.status})`);
|
|
304
313
|
const document: { scope?: string; redirect_uris?: string[] } = await documentResponse.json();
|
|
305
314
|
if (!document.redirect_uris?.includes(redirectUri))
|
|
@@ -368,7 +377,7 @@ export async function revokeAppOAuthSession(): Promise<void> {
|
|
|
368
377
|
const cached = refreshSession;
|
|
369
378
|
clearAppOAuth();
|
|
370
379
|
if (!cached) return;
|
|
371
|
-
const revoke =
|
|
380
|
+
const revoke = validatedEndpointUrl(cached.revocationEndpoint ?? cached.tokenEndpoint);
|
|
372
381
|
if (cached.revocationEndpoint === undefined) revoke.pathname = revoke.pathname.replace(/\/token$/, '/revoke');
|
|
373
382
|
await fetch(revoke, {
|
|
374
383
|
method: 'POST',
|
|
@@ -92,7 +92,10 @@ function loadMermaid(): Promise<Mermaid> {
|
|
|
92
92
|
mermaid.initialize({
|
|
93
93
|
startOnLoad: false,
|
|
94
94
|
theme: 'default',
|
|
95
|
-
|
|
95
|
+
// Diagram source comes from LLM output and documents, so it is untrusted. 'strict' makes Mermaid
|
|
96
|
+
// sanitize the whole SVG with DOMPurify, drop `javascript:` link targets and ignore click callbacks;
|
|
97
|
+
// 'loose' let `click A href "javascript:…"` through to the page.
|
|
98
|
+
securityLevel: 'strict',
|
|
96
99
|
fontFamily: MERMAID_FONT_FAMILY,
|
|
97
100
|
suppressErrorRendering: true,
|
|
98
101
|
flowchart: {
|
|
@@ -202,7 +205,7 @@ export function MermaidDiagram({ code, className }: MermaidDiagramProps) {
|
|
|
202
205
|
<div
|
|
203
206
|
ref={containerRef}
|
|
204
207
|
className={`my-4 w-full overflow-x-auto [&_svg]:mx-auto [&_svg]:w-full [&_svg]:h-auto [&_svg]:max-w-full ${className || ''}`}
|
|
205
|
-
// biome-ignore lint/security/noDangerouslySetInnerHtml:
|
|
208
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: Mermaid sanitizes its SVG output under securityLevel 'strict'
|
|
206
209
|
dangerouslySetInnerHTML={{ __html: svg }}
|
|
207
210
|
/>
|
|
208
211
|
);
|
|
@@ -94,6 +94,7 @@ export function DropZone({ onDrop, message, buttonLabel, allowFolders = true, cl
|
|
|
94
94
|
|
|
95
95
|
const handleDrop = async (e: React.DragEvent) => {
|
|
96
96
|
e.preventDefault();
|
|
97
|
+
e.stopPropagation();
|
|
97
98
|
setIsDragging(false);
|
|
98
99
|
|
|
99
100
|
if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
|