mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-06-11 22:21:01 +00:00
06ed9734c6
* Faz 3.1 — All CI jobs moved to self-hosted pwap-runner (DEV VPS).
No more dependency on GitHub-hosted runners — supply-chain attack
surface from GHA runner image compromise eliminated.
* Faz 3.3 — Automatic rollback on health-check fail. Each deploy stamps
/.deploy-sha into the artifact. On health-check failure, the deploy
job reads the previous SHA from the live site, pulls that image, and
redeploys. Telegram notification differentiates: rolled-back-OK,
rollback-also-failed, no-prev-available, manual-rollback-needed.
* E.3 — cosign keyless image signing. build-image signs the GHCR
manifest via Sigstore Fulcio (OIDC, no long-lived keys). deploy-app
and deploy-pex verify the signature before extracting /dist —
unsigned or tampered images cannot deploy. Identity-pinned to this
workflow file.
* E.5 — Subresource Integrity (SRI). vite-plugin-subresource-integrity
injects sha384 integrity= into <script>/<link> tags at build time.
CDN/proxy compromise cannot inject tampered JS — browser blocks on
hash mismatch.
* E.2 — Dependabot triage. 14 alerts: 7 high + 4 moderate cleared via
npm audit fix + npm overrides (elliptic, create-ecdh). 6 low
(transitive in vite-plugin-node-polyfills chain) accepted; the
upstream fix proposes a semver-major DOWNGRADE which makes no sense.
* E.1 — Branch protection on main: CI Gate ✅ required, 1 review
required, force-push and deletion blocked.
92 lines
3.7 KiB
TypeScript
92 lines
3.7 KiB
TypeScript
/// <reference types="vitest" />
|
||
import { defineConfig } from "vitest/config";
|
||
import react from "@vitejs/plugin-react-swc";
|
||
import path from "path";
|
||
import { nodePolyfills } from 'vite-plugin-node-polyfills';
|
||
import subresourceIntegrity from 'vite-plugin-subresource-integrity';
|
||
|
||
// https://vitejs.dev/config/
|
||
export default defineConfig(({ command }) => ({
|
||
test: {
|
||
globals: true,
|
||
environment: 'jsdom',
|
||
setupFiles: './src/tests/setup.ts',
|
||
alias: {
|
||
'vite-plugin-node-polyfills/shims/buffer': path.resolve(__dirname, './src/tests/mocks/buffer-shim.ts'),
|
||
'vite-plugin-node-polyfills/shims/global': path.resolve(__dirname, './src/tests/mocks/global-shim.ts'),
|
||
'vite-plugin-node-polyfills/shims/process': path.resolve(__dirname, './src/tests/mocks/process-shim.ts'),
|
||
},
|
||
},
|
||
server: {
|
||
host: "::",
|
||
port: 8082,
|
||
strictPort: false, // Allow automatic port selection if 8082 is busy
|
||
hmr: {
|
||
protocol: 'ws',
|
||
host: 'localhost',
|
||
},
|
||
watch: {
|
||
usePolling: true,
|
||
},
|
||
},
|
||
plugins: [
|
||
react(),
|
||
nodePolyfills({
|
||
globals: {
|
||
Buffer: true,
|
||
global: true,
|
||
process: true,
|
||
},
|
||
protocolImports: true,
|
||
}),
|
||
// SRI: production build sırasında <script>/<link> tag'lerine
|
||
// sha384 integrity hash ekle. CDN/proxy compromise olsa bile
|
||
// tampered asset browser tarafından load edilmez.
|
||
command === 'build' ? subresourceIntegrity({ algorithm: 'sha384' }) : null,
|
||
].filter(Boolean),
|
||
resolve: {
|
||
mainFields: ['browser', 'module', 'main', 'exports'],
|
||
alias: {
|
||
// Rollup cannot resolve virtual shim modules in production — alias to real file.
|
||
// Dev mode: the plugin's own virtual module handles it; do NOT override it here.
|
||
...(command === 'build' ? {
|
||
'vite-plugin-node-polyfills/shims/process': path.resolve(__dirname, './src/lib/process-shim.ts'),
|
||
} : {}),
|
||
"@": path.resolve(__dirname, "./src"),
|
||
"@pezkuwi/i18n": path.resolve(__dirname, "../shared/i18n"),
|
||
"@pezkuwi/lib": path.resolve(__dirname, "../shared/lib"),
|
||
"@pezkuwi/utils": path.resolve(__dirname, "../shared/utils"),
|
||
"@pezkuwi/theme": path.resolve(__dirname, "../shared/theme"),
|
||
"@local/types": path.resolve(__dirname, "../shared/types"),
|
||
"@pezkuwi/components": path.resolve(__dirname, "../shared/components"),
|
||
"@shared": path.resolve(__dirname, "../shared"),
|
||
},
|
||
dedupe: ['react', 'lucide-react', 'sonner', '@pezkuwi/util-crypto', '@pezkuwi/util', '@pezkuwi/api', '@pezkuwi/extension-dapp', '@pezkuwi/keyring'],
|
||
},
|
||
optimizeDeps: {
|
||
include: ['@pezkuwi/util-crypto', '@pezkuwi/util', '@pezkuwi/api', '@pezkuwi/extension-dapp', '@pezkuwi/keyring', 'buffer'],
|
||
},
|
||
build: {
|
||
rollupOptions: {
|
||
external: [],
|
||
onwarn(warning, warn) {
|
||
// Suppress the buffer shim warning - it's handled by vite-plugin-node-polyfills
|
||
if (warning.message?.includes('vite-plugin-node-polyfills/shims/buffer')) {
|
||
return;
|
||
}
|
||
warn(warning);
|
||
},
|
||
output: {
|
||
manualChunks: {
|
||
'pezkuwi': ['@pezkuwi/api', '@pezkuwi/extension-dapp', '@pezkuwi/keyring', '@pezkuwi/util', '@pezkuwi/util-crypto'],
|
||
'vendor': ['react', 'react-dom', 'react-router-dom'],
|
||
'ui': ['@radix-ui/react-dialog', '@radix-ui/react-dropdown-menu', '@radix-ui/react-select', '@radix-ui/react-tabs', '@radix-ui/react-toast'],
|
||
'forms': ['react-hook-form', '@hookform/resolvers', 'zod'],
|
||
'i18n': ['i18next', 'react-i18next', 'i18next-browser-languagedetector']
|
||
}
|
||
}
|
||
},
|
||
chunkSizeWarningLimit: 600
|
||
},
|
||
// assetsInclude: ['**/*.json'], // Disabled: interferes with node_modules JSON imports (crypto-browserify)
|
||
})); |