specra 0.1.13 → 0.2.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/LICENSE.MD +25 -4
- package/README.md +67 -58
- package/config/specra.config.schema.json +16 -0
- package/config/svelte-config.js +63 -0
- package/dist/api-parser.types.d.ts +59 -0
- package/dist/api-parser.types.js +5 -0
- package/dist/api.types.d.ts +137 -0
- package/dist/api.types.js +5 -0
- package/dist/category.d.ts +21 -0
- package/dist/category.js +48 -0
- package/dist/components/ConfigProvider.svelte +13 -0
- package/dist/components/ConfigProvider.svelte.d.ts +31 -0
- package/dist/components/docs/Accordion.svelte +18 -0
- package/dist/components/docs/Accordion.svelte.d.ts +10 -0
- package/dist/components/docs/AccordionItem.svelte +41 -0
- package/dist/components/docs/AccordionItem.svelte.d.ts +10 -0
- package/dist/components/docs/Badge.svelte +28 -0
- package/dist/components/docs/Badge.svelte.d.ts +9 -0
- package/dist/components/docs/Breadcrumb.svelte +80 -0
- package/dist/components/docs/Breadcrumb.svelte.d.ts +8 -0
- package/dist/components/docs/Callout.svelte +96 -0
- package/dist/components/docs/Callout.svelte.d.ts +10 -0
- package/dist/components/docs/Card.svelte +63 -0
- package/dist/components/docs/Card.svelte.d.ts +12 -0
- package/dist/components/docs/CardGrid.svelte +24 -0
- package/dist/components/docs/CardGrid.svelte.d.ts +8 -0
- package/dist/components/docs/CategoryIndex.svelte +110 -0
- package/dist/components/docs/CategoryIndex.svelte.d.ts +29 -0
- package/dist/components/docs/CodeBlock.svelte +172 -0
- package/dist/components/docs/CodeBlock.svelte.d.ts +8 -0
- package/dist/components/docs/Column.svelte +25 -0
- package/dist/components/docs/Column.svelte.d.ts +8 -0
- package/dist/components/docs/Columns.svelte +38 -0
- package/dist/components/docs/Columns.svelte.d.ts +13 -0
- package/dist/components/docs/DevModeBadge.svelte +15 -0
- package/dist/components/docs/DevModeBadge.svelte.d.ts +18 -0
- package/dist/components/docs/DocBadge.svelte +28 -0
- package/dist/components/docs/DocBadge.svelte.d.ts +9 -0
- package/dist/components/docs/DocLayout.svelte +107 -0
- package/dist/components/docs/DocLayout.svelte.d.ts +32 -0
- package/dist/components/docs/DocLoading.svelte +53 -0
- package/dist/components/docs/DocLoading.svelte.d.ts +18 -0
- package/dist/components/docs/DocMetadata.svelte +106 -0
- package/dist/components/docs/DocMetadata.svelte.d.ts +18 -0
- package/dist/components/docs/DocNavigation.svelte +56 -0
- package/dist/components/docs/DocNavigation.svelte.d.ts +12 -0
- package/dist/components/docs/DocTags.svelte +22 -0
- package/dist/components/docs/DocTags.svelte.d.ts +6 -0
- package/dist/components/docs/DraftBadge.svelte +10 -0
- package/dist/components/docs/DraftBadge.svelte.d.ts +18 -0
- package/dist/components/docs/Footer.svelte +72 -0
- package/dist/components/docs/Footer.svelte.d.ts +7 -0
- package/dist/components/docs/Frame.svelte +27 -0
- package/dist/components/docs/Frame.svelte.d.ts +9 -0
- package/dist/components/docs/Header.svelte +123 -0
- package/dist/components/docs/Header.svelte.d.ts +9 -0
- package/dist/components/docs/HeaderWithMenu.svelte +34 -0
- package/dist/components/docs/HeaderWithMenu.svelte.d.ts +17 -0
- package/dist/components/docs/HotReloadIndicator.svelte +44 -0
- package/dist/components/docs/HotReloadIndicator.svelte.d.ts +3 -0
- package/dist/components/docs/Icon.svelte +103 -0
- package/dist/components/docs/Icon.svelte.d.ts +11 -0
- package/dist/components/docs/Image.svelte +88 -0
- package/dist/components/docs/Image.svelte.d.ts +11 -0
- package/dist/components/docs/ImageCard.svelte +91 -0
- package/dist/components/docs/ImageCard.svelte.d.ts +12 -0
- package/dist/components/docs/ImageCardGrid.svelte +25 -0
- package/dist/components/docs/ImageCardGrid.svelte.d.ts +8 -0
- package/dist/components/docs/LayoutProviders.svelte +57 -0
- package/dist/components/docs/LayoutProviders.svelte.d.ts +9 -0
- package/dist/components/docs/Logo.svelte +25 -0
- package/dist/components/docs/Logo.svelte.d.ts +11 -0
- package/dist/components/docs/Math.svelte +54 -0
- package/dist/components/docs/Math.svelte.d.ts +7 -0
- package/dist/components/docs/MdxContent.svelte +41 -0
- package/dist/components/docs/MdxHotReload.svelte +78 -0
- package/dist/components/docs/MdxHotReload.svelte.d.ts +9 -0
- package/dist/components/docs/MdxLayout.svelte +16 -0
- package/dist/components/docs/MdxLayout.svelte.d.ts +6 -0
- package/dist/components/docs/Mermaid.svelte +88 -0
- package/dist/components/docs/Mermaid.svelte.d.ts +7 -0
- package/dist/components/docs/MobileDocLayout.svelte +211 -0
- package/dist/components/docs/MobileDocLayout.svelte.d.ts +35 -0
- package/dist/components/docs/MobileSidebar.svelte +122 -0
- package/dist/components/docs/MobileSidebar.svelte.d.ts +31 -0
- package/dist/components/docs/MobileSidebarWrapper.svelte +122 -0
- package/dist/components/docs/MobileSidebarWrapper.svelte.d.ts +32 -0
- package/dist/components/docs/NotFoundContent.svelte +40 -0
- package/dist/components/docs/NotFoundContent.svelte.d.ts +6 -0
- package/dist/components/docs/SearchHighlight.svelte +116 -0
- package/dist/components/docs/SearchHighlight.svelte.d.ts +3 -0
- package/dist/components/docs/SearchModal.svelte +239 -0
- package/dist/components/docs/SearchModal.svelte.d.ts +9 -0
- package/dist/components/docs/Sidebar.svelte +69 -0
- package/dist/components/docs/Sidebar.svelte.d.ts +31 -0
- package/dist/components/docs/SidebarMenuItems.svelte +344 -0
- package/dist/components/docs/SidebarMenuItems.svelte.d.ts +33 -0
- package/dist/components/docs/SidebarSkeleton.svelte +50 -0
- package/dist/components/docs/SidebarSkeleton.svelte.d.ts +18 -0
- package/dist/components/docs/SiteBanner.svelte +92 -0
- package/dist/components/docs/SiteBanner.svelte.d.ts +7 -0
- package/dist/components/docs/Step.svelte +44 -0
- package/dist/components/docs/Step.svelte.d.ts +8 -0
- package/dist/components/docs/Steps.svelte +15 -0
- package/dist/components/docs/Steps.svelte.d.ts +7 -0
- package/dist/components/docs/Tab.svelte +40 -0
- package/dist/components/docs/Tab.svelte.d.ts +8 -0
- package/dist/components/docs/TabGroups.svelte +183 -0
- package/dist/components/docs/TabGroups.svelte.d.ts +25 -0
- package/dist/components/docs/TableOfContents.svelte +100 -0
- package/dist/components/docs/TableOfContents.svelte.d.ts +9 -0
- package/dist/components/docs/Tabs.svelte +69 -0
- package/dist/components/docs/Tabs.svelte.d.ts +8 -0
- package/dist/components/docs/ThemeToggle.svelte +16 -0
- package/dist/components/docs/ThemeToggle.svelte.d.ts +18 -0
- package/dist/components/docs/Tooltip.svelte +44 -0
- package/dist/components/docs/Tooltip.svelte.d.ts +10 -0
- package/dist/components/docs/VersionSwitcher.svelte +95 -0
- package/dist/components/docs/VersionSwitcher.svelte.d.ts +7 -0
- package/dist/components/docs/Video.svelte +84 -0
- package/dist/components/docs/Video.svelte.d.ts +12 -0
- package/dist/components/docs/api/ApiEndpoint.svelte +61 -0
- package/dist/components/docs/api/ApiEndpoint.svelte.d.ts +11 -0
- package/dist/components/docs/api/ApiParams.svelte +80 -0
- package/dist/components/docs/api/ApiParams.svelte.d.ts +14 -0
- package/dist/components/docs/api/ApiPlayground.svelte +259 -0
- package/dist/components/docs/api/ApiPlayground.svelte.d.ts +16 -0
- package/dist/components/docs/api/ApiReference.svelte +278 -0
- package/dist/components/docs/api/ApiReference.svelte.d.ts +23 -0
- package/dist/components/docs/api/ApiResponse.svelte +66 -0
- package/dist/components/docs/api/ApiResponse.svelte.d.ts +9 -0
- package/dist/components/docs/api/index.d.ts +5 -0
- package/dist/components/docs/api/index.js +5 -0
- package/dist/components/docs/componentTextProps.d.ts +3 -0
- package/dist/components/docs/componentTextProps.js +61 -0
- package/dist/components/docs/index.d.ts +54 -0
- package/dist/components/docs/index.js +56 -0
- package/dist/components/global/VersionNotFound.svelte +48 -0
- package/dist/components/global/VersionNotFound.svelte.d.ts +7 -0
- package/dist/components/global/index.d.ts +1 -0
- package/dist/components/global/index.js +1 -0
- package/dist/components/index.d.ts +6 -822
- package/dist/components/index.js +11 -3854
- package/dist/components/ui/Badge.svelte +48 -0
- package/dist/components/ui/Badge.svelte.d.ts +15 -0
- package/dist/components/ui/Button.svelte +58 -0
- package/dist/components/ui/Button.svelte.d.ts +17 -0
- package/dist/components/ui/Dialog.svelte +16 -0
- package/dist/components/ui/Dialog.svelte.d.ts +9 -0
- package/dist/components/ui/DialogClose.svelte +16 -0
- package/dist/components/ui/DialogClose.svelte.d.ts +9 -0
- package/dist/components/ui/DialogContent.svelte +43 -0
- package/dist/components/ui/DialogContent.svelte.d.ts +10 -0
- package/dist/components/ui/DialogDescription.svelte +21 -0
- package/dist/components/ui/DialogDescription.svelte.d.ts +9 -0
- package/dist/components/ui/DialogFooter.svelte +20 -0
- package/dist/components/ui/DialogFooter.svelte.d.ts +9 -0
- package/dist/components/ui/DialogHeader.svelte +20 -0
- package/dist/components/ui/DialogHeader.svelte.d.ts +9 -0
- package/dist/components/ui/DialogTitle.svelte +21 -0
- package/dist/components/ui/DialogTitle.svelte.d.ts +9 -0
- package/dist/components/ui/Input.svelte +23 -0
- package/dist/components/ui/Input.svelte.d.ts +8 -0
- package/dist/components/ui/Textarea.svelte +19 -0
- package/dist/components/ui/Textarea.svelte.d.ts +7 -0
- package/dist/components/ui/index.d.ts +11 -0
- package/dist/components/ui/index.js +11 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +9 -0
- package/dist/config.schema.json +471 -0
- package/dist/config.server.d.ts +46 -0
- package/dist/config.server.js +149 -0
- package/dist/{mdx-ColN3Cyg.d.mts → config.types.d.ts} +22 -75
- package/dist/config.types.js +39 -0
- package/dist/dev-utils.d.ts +29 -0
- package/dist/dev-utils.js +63 -0
- package/dist/index.d.ts +19 -4
- package/dist/index.js +25 -4861
- package/dist/mdx-cache.d.ts +41 -0
- package/dist/mdx-cache.js +160 -0
- package/dist/mdx-components.js +50 -1931
- package/dist/mdx-security.d.ts +76 -0
- package/dist/mdx-security.js +217 -0
- package/dist/mdx.d.ts +73 -0
- package/dist/mdx.js +1099 -0
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.js +2 -0
- package/dist/middleware/security.d.ts +22 -47
- package/dist/middleware/security.js +111 -137
- package/dist/parsers/base-parser.d.ts +14 -0
- package/dist/parsers/base-parser.js +1 -0
- package/dist/parsers/index.d.ts +16 -0
- package/dist/parsers/index.js +51 -0
- package/dist/parsers/openapi-parser.d.ts +18 -0
- package/dist/parsers/openapi-parser.js +209 -0
- package/dist/parsers/postman-parser.d.ts +20 -0
- package/dist/parsers/postman-parser.js +260 -0
- package/dist/parsers/specra-parser.d.ts +10 -0
- package/dist/parsers/specra-parser.js +18 -0
- package/dist/redirects.d.ts +12 -0
- package/dist/redirects.js +30 -0
- package/dist/remark-code-meta.d.ts +6 -0
- package/dist/remark-code-meta.js +21 -0
- package/dist/sidebar-utils.d.ts +59 -0
- package/dist/sidebar-utils.js +144 -0
- package/dist/stores/config.d.ts +20 -0
- package/dist/stores/config.js +45 -0
- package/dist/stores/index.d.ts +4 -0
- package/dist/stores/index.js +4 -0
- package/dist/stores/sidebar.d.ts +7 -0
- package/dist/stores/sidebar.js +12 -0
- package/dist/stores/tabs.d.ts +6 -0
- package/dist/stores/tabs.js +41 -0
- package/dist/stores/theme.d.ts +7 -0
- package/dist/stores/theme.js +75 -0
- package/dist/{styles.css → styles/globals.css} +136 -6
- package/dist/toc.d.ts +9 -0
- package/dist/toc.js +15 -0
- package/dist/utils.d.ts +13 -0
- package/dist/utils.js +30 -0
- package/package.json +47 -90
- package/dist/app/api/mdx-watch/route.d.mts +0 -10
- package/dist/app/api/mdx-watch/route.d.ts +0 -10
- package/dist/app/api/mdx-watch/route.js +0 -118
- package/dist/app/api/mdx-watch/route.js.map +0 -1
- package/dist/app/api/mdx-watch/route.mjs +0 -91
- package/dist/app/api/mdx-watch/route.mjs.map +0 -1
- package/dist/chunk-6S3EJVEO.mjs +0 -259
- package/dist/chunk-6S3EJVEO.mjs.map +0 -1
- package/dist/chunk-BE7EROIW.mjs +0 -212
- package/dist/chunk-BE7EROIW.mjs.map +0 -1
- package/dist/chunk-CWHRZHZO.mjs +0 -168
- package/dist/chunk-CWHRZHZO.mjs.map +0 -1
- package/dist/chunk-D5VDVYFY.mjs +0 -1325
- package/dist/chunk-D5VDVYFY.mjs.map +0 -1
- package/dist/chunk-WMCO2UX5.mjs +0 -585
- package/dist/chunk-WMCO2UX5.mjs.map +0 -1
- package/dist/chunk-XEMGCPZZ.mjs +0 -475
- package/dist/chunk-XEMGCPZZ.mjs.map +0 -1
- package/dist/components/index.d.mts +0 -822
- package/dist/components/index.js.map +0 -1
- package/dist/components/index.mjs +0 -3741
- package/dist/components/index.mjs.map +0 -1
- package/dist/index.d.mts +0 -4
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -1897
- package/dist/index.mjs.map +0 -1
- package/dist/layouts/index.d.mts +0 -34
- package/dist/layouts/index.d.ts +0 -34
- package/dist/layouts/index.js +0 -453
- package/dist/layouts/index.js.map +0 -1
- package/dist/layouts/index.mjs +0 -173
- package/dist/layouts/index.mjs.map +0 -1
- package/dist/lib/index.d.mts +0 -583
- package/dist/lib/index.d.ts +0 -583
- package/dist/lib/index.js +0 -1595
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/index.mjs +0 -111
- package/dist/lib/index.mjs.map +0 -1
- package/dist/mdx-ColN3Cyg.d.ts +0 -352
- package/dist/mdx-components.d.mts +0 -86
- package/dist/mdx-components.d.ts +0 -86
- package/dist/mdx-components.js.map +0 -1
- package/dist/mdx-components.mjs +0 -206
- package/dist/mdx-components.mjs.map +0 -1
- package/dist/middleware/security.d.mts +0 -82
- package/dist/middleware/security.js.map +0 -1
- package/dist/middleware/security.mjs +0 -84
- package/dist/middleware/security.mjs.map +0 -1
- package/dist/styles.css.map +0 -1
- package/dist/styles.d.mts +0 -2
- package/dist/styles.d.ts +0 -2
- package/dist/styles.js +0 -2
- package/dist/styles.js.map +0 -1
- package/dist/styles.mjs +0 -1
- package/dist/styles.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './security.js';
|
|
@@ -1,82 +1,57 @@
|
|
|
1
|
-
import { NextResponse, NextRequest } from 'next/server';
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* Security Middleware for
|
|
2
|
+
* Security Middleware for SvelteKit
|
|
5
3
|
*
|
|
6
4
|
* Implements:
|
|
7
5
|
* - Content Security Policy (CSP)
|
|
8
6
|
* - Additional security headers
|
|
9
7
|
* - Path traversal protection
|
|
8
|
+
*
|
|
9
|
+
* Usage in hooks.server.ts:
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { sequence } from '@sveltejs/kit/hooks'
|
|
12
|
+
* import { createSecurityHandle } from 'specra/middleware/security'
|
|
13
|
+
*
|
|
14
|
+
* export const handle = sequence(
|
|
15
|
+
* createSecurityHandle(),
|
|
16
|
+
* // ... other handles
|
|
17
|
+
* )
|
|
18
|
+
* ```
|
|
10
19
|
*/
|
|
11
|
-
|
|
20
|
+
import type { Handle } from '@sveltejs/kit';
|
|
12
21
|
/**
|
|
13
22
|
* Security headers configuration
|
|
14
23
|
*/
|
|
15
|
-
declare const SECURITY_HEADERS:
|
|
16
|
-
"X-Frame-Options": string;
|
|
17
|
-
"X-Content-Type-Options": string;
|
|
18
|
-
"X-XSS-Protection": string;
|
|
19
|
-
"Referrer-Policy": string;
|
|
20
|
-
"Permissions-Policy": string;
|
|
21
|
-
};
|
|
24
|
+
export declare const SECURITY_HEADERS: Record<string, string>;
|
|
22
25
|
/**
|
|
23
|
-
* Apply security headers to
|
|
26
|
+
* Apply security headers to a Response
|
|
24
27
|
*/
|
|
25
|
-
declare function applySecurityHeaders(response:
|
|
28
|
+
export declare function applySecurityHeaders(response: Response, options?: {
|
|
26
29
|
customCSP?: string;
|
|
27
30
|
production?: boolean;
|
|
28
|
-
}):
|
|
31
|
+
}): Response;
|
|
29
32
|
/**
|
|
30
33
|
* Validate request path for security issues
|
|
31
34
|
*/
|
|
32
|
-
declare function validateRequestPath(pathname: string): {
|
|
35
|
+
export declare function validateRequestPath(pathname: string): {
|
|
33
36
|
valid: boolean;
|
|
34
37
|
reason?: string;
|
|
35
38
|
};
|
|
36
39
|
/**
|
|
37
|
-
*
|
|
38
|
-
* Add this to your Next.js proxy.ts file
|
|
40
|
+
* Create a SvelteKit handle for security middleware
|
|
39
41
|
*/
|
|
40
|
-
declare function
|
|
42
|
+
export declare function createSecurityHandle(options?: {
|
|
41
43
|
customCSP?: string;
|
|
42
44
|
production?: boolean;
|
|
43
45
|
strictPathValidation?: boolean;
|
|
44
|
-
}):
|
|
45
|
-
/**
|
|
46
|
-
* @deprecated Use createSecurityProxy instead. Middleware is renamed to Proxy in Next.js 16+
|
|
47
|
-
*/
|
|
48
|
-
declare const createSecurityMiddleware: typeof createSecurityProxy;
|
|
49
|
-
/**
|
|
50
|
-
* Example proxy configuration for your project
|
|
51
|
-
*
|
|
52
|
-
* Create this file: proxy.ts (at root of your Next.js app)
|
|
53
|
-
*
|
|
54
|
-
* ```typescript
|
|
55
|
-
* import { createSecurityProxy } from 'specra/middleware/security'
|
|
56
|
-
*
|
|
57
|
-
* export const proxy = createSecurityProxy({
|
|
58
|
-
* production: process.env.NODE_ENV === 'production',
|
|
59
|
-
* strictPathValidation: true,
|
|
60
|
-
* })
|
|
61
|
-
*
|
|
62
|
-
* export const config = {
|
|
63
|
-
* matcher: [
|
|
64
|
-
* // Match all paths except static files
|
|
65
|
-
* '/((?!_next/static|_next/image|favicon.ico).*)',
|
|
66
|
-
* ],
|
|
67
|
-
* }
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
46
|
+
}): Handle;
|
|
70
47
|
/**
|
|
71
48
|
* Validate subdomain/organization isolation
|
|
72
49
|
* Use this if you're building a multi-tenant system
|
|
73
50
|
*/
|
|
74
|
-
declare function validateSubdomainIsolation(
|
|
51
|
+
export declare function validateSubdomainIsolation(hostname: string, pathname: string, options: {
|
|
75
52
|
allowedSubdomains?: string[];
|
|
76
53
|
currentOrg?: string;
|
|
77
54
|
}): {
|
|
78
55
|
valid: boolean;
|
|
79
56
|
reason?: string;
|
|
80
57
|
};
|
|
81
|
-
|
|
82
|
-
export { SECURITY_HEADERS, applySecurityHeaders, createSecurityMiddleware, createSecurityProxy, validateRequestPath, validateSubdomainIsolation };
|
|
@@ -1,144 +1,118 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Security Middleware for SvelteKit
|
|
3
|
+
*
|
|
4
|
+
* Implements:
|
|
5
|
+
* - Content Security Policy (CSP)
|
|
6
|
+
* - Additional security headers
|
|
7
|
+
* - Path traversal protection
|
|
8
|
+
*
|
|
9
|
+
* Usage in hooks.server.ts:
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { sequence } from '@sveltejs/kit/hooks'
|
|
12
|
+
* import { createSecurityHandle } from 'specra/middleware/security'
|
|
13
|
+
*
|
|
14
|
+
* export const handle = sequence(
|
|
15
|
+
* createSecurityHandle(),
|
|
16
|
+
* // ... other handles
|
|
17
|
+
* )
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
import { generateCSPHeader } from '../mdx-security.js';
|
|
21
|
+
/**
|
|
22
|
+
* Security headers configuration
|
|
23
|
+
*/
|
|
24
|
+
export const SECURITY_HEADERS = {
|
|
25
|
+
// Prevent clickjacking
|
|
26
|
+
'X-Frame-Options': 'SAMEORIGIN',
|
|
27
|
+
// Prevent MIME type sniffing
|
|
28
|
+
'X-Content-Type-Options': 'nosniff',
|
|
29
|
+
// Enable XSS protection (legacy browsers)
|
|
30
|
+
'X-XSS-Protection': '1; mode=block',
|
|
31
|
+
// Control referrer information
|
|
32
|
+
'Referrer-Policy': 'strict-origin-when-cross-origin',
|
|
33
|
+
// Permissions Policy (formerly Feature Policy)
|
|
34
|
+
'Permissions-Policy': 'camera=(), microphone=(), geolocation=()',
|
|
9
35
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
SECURITY_HEADERS: () => SECURITY_HEADERS,
|
|
24
|
-
applySecurityHeaders: () => applySecurityHeaders,
|
|
25
|
-
createSecurityMiddleware: () => createSecurityMiddleware,
|
|
26
|
-
createSecurityProxy: () => createSecurityProxy,
|
|
27
|
-
validateRequestPath: () => validateRequestPath,
|
|
28
|
-
validateSubdomainIsolation: () => validateSubdomainIsolation
|
|
29
|
-
});
|
|
30
|
-
module.exports = __toCommonJS(security_exports);
|
|
31
|
-
var import_server = require("next/server");
|
|
32
|
-
|
|
33
|
-
// src/lib/mdx-security.ts
|
|
34
|
-
var CSP_DIRECTIVES = {
|
|
35
|
-
"default-src": ["'self'"],
|
|
36
|
-
"script-src": [
|
|
37
|
-
"'self'",
|
|
38
|
-
"'unsafe-inline'",
|
|
39
|
-
// Required for Next.js
|
|
40
|
-
"'unsafe-eval'"
|
|
41
|
-
// Required for dev mode - remove in production
|
|
42
|
-
],
|
|
43
|
-
"style-src": ["'self'", "'unsafe-inline'"],
|
|
44
|
-
// Required for styled-components/emotion
|
|
45
|
-
"img-src": ["'self'", "data:", "https:"],
|
|
46
|
-
"font-src": ["'self'", "data:"],
|
|
47
|
-
"connect-src": ["'self'"],
|
|
48
|
-
"frame-src": ["'self'"],
|
|
49
|
-
"object-src": ["'none'"],
|
|
50
|
-
"base-uri": ["'self'"],
|
|
51
|
-
"form-action": ["'self'"],
|
|
52
|
-
"frame-ancestors": ["'self'"],
|
|
53
|
-
"upgrade-insecure-requests": []
|
|
54
|
-
};
|
|
55
|
-
function generateCSPHeader(customDirectives, production = true) {
|
|
56
|
-
const directives = { ...CSP_DIRECTIVES, ...customDirectives };
|
|
57
|
-
if (production && directives["script-src"]) {
|
|
58
|
-
directives["script-src"] = directives["script-src"].filter(
|
|
59
|
-
(src) => src !== "'unsafe-eval'"
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
return Object.entries(directives).map(([key, values]) => `${key} ${values.join(" ")}`).join("; ");
|
|
36
|
+
/**
|
|
37
|
+
* Apply security headers to a Response
|
|
38
|
+
*/
|
|
39
|
+
export function applySecurityHeaders(response, options) {
|
|
40
|
+
const { customCSP, production = true } = options || {};
|
|
41
|
+
// Apply standard security headers
|
|
42
|
+
for (const [key, value] of Object.entries(SECURITY_HEADERS)) {
|
|
43
|
+
response.headers.set(key, value);
|
|
44
|
+
}
|
|
45
|
+
// Apply CSP
|
|
46
|
+
const csp = customCSP || generateCSPHeader(undefined, production);
|
|
47
|
+
response.headers.set('Content-Security-Policy', csp);
|
|
48
|
+
return response;
|
|
63
49
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Validate request path for security issues
|
|
52
|
+
*/
|
|
53
|
+
export function validateRequestPath(pathname) {
|
|
54
|
+
// Decode the pathname to catch encoded attacks
|
|
55
|
+
const decoded = decodeURIComponent(pathname);
|
|
56
|
+
// Check for path traversal
|
|
57
|
+
if (decoded.includes('../') || decoded.includes('..\\')) {
|
|
58
|
+
return { valid: false, reason: 'Path traversal detected' };
|
|
59
|
+
}
|
|
60
|
+
// Check for encoded path traversal
|
|
61
|
+
if (decoded.includes('%2e%2e') ||
|
|
62
|
+
decoded.includes('%252e%252e') ||
|
|
63
|
+
pathname.includes('%2e%2e') ||
|
|
64
|
+
pathname.includes('%252e%252e')) {
|
|
65
|
+
return { valid: false, reason: 'Encoded path traversal detected' };
|
|
66
|
+
}
|
|
67
|
+
// Check for null bytes
|
|
68
|
+
if (decoded.includes('\0') || pathname.includes('%00')) {
|
|
69
|
+
return { valid: false, reason: 'Null byte injection detected' };
|
|
70
|
+
}
|
|
71
|
+
return { valid: true };
|
|
86
72
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Create a SvelteKit handle for security middleware
|
|
75
|
+
*/
|
|
76
|
+
export function createSecurityHandle(options) {
|
|
77
|
+
return async ({ event, resolve }) => {
|
|
78
|
+
const { strictPathValidation = true } = options || {};
|
|
79
|
+
// Validate request path
|
|
80
|
+
if (strictPathValidation) {
|
|
81
|
+
const pathValidation = validateRequestPath(event.url.pathname);
|
|
82
|
+
if (!pathValidation.valid) {
|
|
83
|
+
const ip = event.request.headers.get('x-forwarded-for') ||
|
|
84
|
+
event.request.headers.get('x-real-ip') ||
|
|
85
|
+
'unknown';
|
|
86
|
+
console.warn(`[Security] Blocked request: ${pathValidation.reason}`, {
|
|
87
|
+
path: event.url.pathname,
|
|
88
|
+
ip,
|
|
89
|
+
});
|
|
90
|
+
return new Response('Bad Request', { status: 400 });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Continue with the request and apply security headers
|
|
94
|
+
const response = await resolve(event);
|
|
95
|
+
return applySecurityHeaders(response, options);
|
|
96
|
+
};
|
|
99
97
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
});
|
|
111
|
-
return new import_server.NextResponse("Bad Request", { status: 400 });
|
|
112
|
-
}
|
|
98
|
+
/**
|
|
99
|
+
* Validate subdomain/organization isolation
|
|
100
|
+
* Use this if you're building a multi-tenant system
|
|
101
|
+
*/
|
|
102
|
+
export function validateSubdomainIsolation(hostname, pathname, options) {
|
|
103
|
+
const { allowedSubdomains, currentOrg } = options;
|
|
104
|
+
const subdomain = hostname.split('.')[0];
|
|
105
|
+
// If allowlist is provided, validate against it
|
|
106
|
+
if (allowedSubdomains && !allowedSubdomains.includes(subdomain)) {
|
|
107
|
+
return { valid: false, reason: 'Subdomain not in allowlist' };
|
|
113
108
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const hostname = request.headers.get("host") || "";
|
|
122
|
-
const subdomain = hostname.split(".")[0];
|
|
123
|
-
if (allowedSubdomains && !allowedSubdomains.includes(subdomain)) {
|
|
124
|
-
return { valid: false, reason: "Subdomain not in allowlist" };
|
|
125
|
-
}
|
|
126
|
-
const pathMatch = request.nextUrl.pathname.match(/\/(static|assets|_.*?)\/([^/]+)/);
|
|
127
|
-
if (pathMatch && currentOrg) {
|
|
128
|
-
const pathOrg = pathMatch[2];
|
|
129
|
-
if (pathOrg !== currentOrg) {
|
|
130
|
-
return { valid: false, reason: "Cross-organization access detected" };
|
|
109
|
+
// Check for subdomain mismatch in paths
|
|
110
|
+
const pathMatch = pathname.match(/\/(static|assets|_.*?)\/([^/]+)/);
|
|
111
|
+
if (pathMatch && currentOrg) {
|
|
112
|
+
const pathOrg = pathMatch[2];
|
|
113
|
+
if (pathOrg !== currentOrg) {
|
|
114
|
+
return { valid: false, reason: 'Cross-organization access detected' };
|
|
115
|
+
}
|
|
131
116
|
}
|
|
132
|
-
|
|
133
|
-
return { valid: true };
|
|
117
|
+
return { valid: true };
|
|
134
118
|
}
|
|
135
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
136
|
-
0 && (module.exports = {
|
|
137
|
-
SECURITY_HEADERS,
|
|
138
|
-
applySecurityHeaders,
|
|
139
|
-
createSecurityMiddleware,
|
|
140
|
-
createSecurityProxy,
|
|
141
|
-
validateRequestPath,
|
|
142
|
-
validateSubdomainIsolation
|
|
143
|
-
});
|
|
144
|
-
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SpecraApiSpec } from "../api-parser.types";
|
|
2
|
+
/**
|
|
3
|
+
* Base interface for all API spec parsers
|
|
4
|
+
*/
|
|
5
|
+
export interface ApiSpecParser {
|
|
6
|
+
/**
|
|
7
|
+
* Parse the input spec and convert to Specra format
|
|
8
|
+
*/
|
|
9
|
+
parse(input: any): SpecraApiSpec;
|
|
10
|
+
/**
|
|
11
|
+
* Validate if the input is in the expected format
|
|
12
|
+
*/
|
|
13
|
+
validate(input: any): boolean;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SpecraApiSpec } from "../api-parser.types";
|
|
2
|
+
import type { ApiSpecParser } from "./base-parser";
|
|
3
|
+
import { SpecraParser } from "./specra-parser";
|
|
4
|
+
import { OpenApiParser } from "./openapi-parser";
|
|
5
|
+
import { PostmanParser } from "./postman-parser";
|
|
6
|
+
export type ParserType = "auto" | "specra" | "openapi" | "postman";
|
|
7
|
+
/**
|
|
8
|
+
* Auto-detect the parser type based on the input structure
|
|
9
|
+
*/
|
|
10
|
+
export declare function detectParserType(input: any): ParserType;
|
|
11
|
+
/**
|
|
12
|
+
* Parse an API spec using the specified or auto-detected parser
|
|
13
|
+
*/
|
|
14
|
+
export declare function parseApiSpec(input: any, parserType?: ParserType): SpecraApiSpec;
|
|
15
|
+
export { SpecraParser, OpenApiParser, PostmanParser };
|
|
16
|
+
export type { ApiSpecParser };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { SpecraParser } from "./specra-parser";
|
|
2
|
+
import { OpenApiParser } from "./openapi-parser";
|
|
3
|
+
import { PostmanParser } from "./postman-parser";
|
|
4
|
+
/**
|
|
5
|
+
* Registry of all available parsers
|
|
6
|
+
*/
|
|
7
|
+
const parsers = new Map([
|
|
8
|
+
["specra", new SpecraParser()],
|
|
9
|
+
["openapi", new OpenApiParser()],
|
|
10
|
+
["postman", new PostmanParser()],
|
|
11
|
+
]);
|
|
12
|
+
/**
|
|
13
|
+
* Auto-detect the parser type based on the input structure
|
|
14
|
+
*/
|
|
15
|
+
export function detectParserType(input) {
|
|
16
|
+
if (!input || typeof input !== "object") {
|
|
17
|
+
throw new Error("Invalid API spec: input must be an object");
|
|
18
|
+
}
|
|
19
|
+
// Check for Postman Collection
|
|
20
|
+
if (input.info?.schema?.includes("v2")) {
|
|
21
|
+
return "postman";
|
|
22
|
+
}
|
|
23
|
+
// Check for OpenAPI/Swagger
|
|
24
|
+
if (input.openapi || input.swagger) {
|
|
25
|
+
return "openapi";
|
|
26
|
+
}
|
|
27
|
+
// Check for Specra format
|
|
28
|
+
if (input.endpoints && Array.isArray(input.endpoints)) {
|
|
29
|
+
return "specra";
|
|
30
|
+
}
|
|
31
|
+
throw new Error("Unable to auto-detect API spec format. Supported formats: Specra, OpenAPI 3.x, Postman Collection v2.x");
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parse an API spec using the specified or auto-detected parser
|
|
35
|
+
*/
|
|
36
|
+
export function parseApiSpec(input, parserType = "auto") {
|
|
37
|
+
// Auto-detect if needed
|
|
38
|
+
const actualType = parserType === "auto" ? detectParserType(input) : parserType;
|
|
39
|
+
// Get the parser
|
|
40
|
+
const parser = parsers.get(actualType);
|
|
41
|
+
if (!parser) {
|
|
42
|
+
throw new Error(`Unknown parser type: ${actualType}`);
|
|
43
|
+
}
|
|
44
|
+
// Validate and parse
|
|
45
|
+
if (!parser.validate(input)) {
|
|
46
|
+
throw new Error(`Input does not match ${actualType} format`);
|
|
47
|
+
}
|
|
48
|
+
return parser.parse(input);
|
|
49
|
+
}
|
|
50
|
+
// Export parsers for direct use
|
|
51
|
+
export { SpecraParser, OpenApiParser, PostmanParser };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SpecraApiSpec } from "../api-parser.types";
|
|
2
|
+
import type { ApiSpecParser } from "./base-parser";
|
|
3
|
+
/**
|
|
4
|
+
* Parser for OpenAPI 3.0/3.1 specifications
|
|
5
|
+
*/
|
|
6
|
+
export declare class OpenApiParser implements ApiSpecParser {
|
|
7
|
+
validate(input: any): boolean;
|
|
8
|
+
parse(input: any): SpecraApiSpec;
|
|
9
|
+
private extractBaseUrl;
|
|
10
|
+
private extractAuth;
|
|
11
|
+
private parseOperation;
|
|
12
|
+
private convertPathParams;
|
|
13
|
+
private parseParameters;
|
|
14
|
+
private parseRequestBody;
|
|
15
|
+
private parseResponses;
|
|
16
|
+
private generateExample;
|
|
17
|
+
private resolveRef;
|
|
18
|
+
}
|