feat: harden firewall policies telemetry and operations
quality / changes (push) Successful in 7s
quality / commitlint (push) Skipped
quality / openapi (push) Successful in 30s
quality / web (push) Successful in 1m3s
quality / api (push) Successful in 1m15s
quality / linux-agent-smoke (push) Failing after 27s
quality / docker-check (push) Failing after 2m28s
CD / quality (push) Failing after 5m52s
CD / publish (push) Skipped

Implement reliable agent apply, telemetry v2, analytics retention, guarded rollouts, enrollment, labels and webhooks. Improve ReUI frontend data safety and bounded list loading, and add Docker smoke, recovery and resource checks. Document local verification and pending native acceptance.
This commit is contained in:
Denozordec committed 2026-10-26 13:10:58 +07:00
1 parent aa475848fd
commit 9fa6269174
242 files changed
+19872 -3057

No files matched your search

+15 -13
View File
@@ -16,23 +16,22 @@ COPY packages/db/package.json packages/db/
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
pnpm install --frozen-lockfile
FROM deps AS build
COPY apps/web apps/web
FROM deps AS api-build
COPY apps/api apps/api
COPY packages/ui packages/ui
COPY packages/shared packages/shared
COPY packages/db packages/db
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
pnpm turbo build --filter=@evofw/web --filter=@evofw/api \
pnpm turbo build --filter=@evofw/api \
&& pnpm --filter @evofw/api deploy --prod /out \
&& cp -r apps/web/dist /out/static \
&& mkdir -p /out/dist/agent-scripts \
&& cp -r apps/api/src/agent-scripts/* /out/dist/agent-scripts/ \
&& rm -rf /out/src /out/test /out/.turbo \
&& rm -rf /out/node_modules/@evofw/db/src /out/node_modules/@evofw/db/.turbo \
&& rm -rf /out/node_modules/@evofw/shared/src /out/node_modules/@evofw/shared/.turbo \
&& find /out -mindepth 1 -maxdepth 1 ! -name dist ! -name node_modules ! -name package.json -exec rm -rf {} + \
&& find /out -name '*.map' -delete
FROM deps AS web-build
COPY apps/web apps/web
COPY packages/ui packages/ui
COPY packages/shared packages/shared
RUN pnpm turbo build --filter=@evofw/web
FROM ${BASE_NODE} AS runtime
WORKDIR /app
RUN apk add --no-cache ca-certificates
@@ -46,9 +45,12 @@ ENV NODE_ENV=production \
APP_VERSION=${VERSION} \
GIT_SHA=${GIT_SHA} \
BUILD_TIME=${BUILD_TIME}
COPY --from=build /out ./
COPY --from=api-build /out ./
COPY --from=web-build /repo/apps/web/dist ./static
COPY deploy/docker/evofw/sqlite-backup.mjs ./tools/sqlite-backup.mjs
EXPOSE 8080
VOLUME ["/data"]
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD ["node", "-e", "fetch('http://127.0.0.1:8080/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
HEALTHCHECK --interval=30s --timeout=5s --start-period=40s --retries=3 \
CMD ["node", "-e", "fetch('http://127.0.0.1:'+(process.env.SERVER_PORT||8080)+'/ready',{signal:AbortSignal.timeout(4000)}).then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
STOPSIGNAL SIGTERM
CMD ["node", "dist/server.js"]
+41
View File
@@ -0,0 +1,41 @@
import { createRequire } from 'node:module'
import { resolve, dirname } from 'node:path'
import { existsSync, mkdirSync, renameSync, rmSync } from 'node:fs'
// Resolve through the production workspace package; pnpm isolates transitive deps.
const require = createRequire(resolve('node_modules/@evofw/db/package.json'))
const Database = require('better-sqlite3')
const [mode, input, output, offline] = process.argv.slice(2)
if (!['backup', 'restore', 'verify'].includes(mode) || !input || (mode !== 'verify' && !output)) {
throw new Error('Usage: sqlite-backup.mjs backup|verify|restore INPUT [OUTPUT] [--offline]')
}
if (mode === 'restore' && offline !== '--offline') throw new Error('Restore requires a stopped volume and --offline')
if (output && resolve(input) === resolve(output)) throw new Error('Input and output must differ')
if (mode === 'backup' && existsSync(output)) throw new Error('Backup destination already exists')
const source = new Database(input, { readonly: true, fileMustExist: true })
let temporary
try {
if (source.pragma('integrity_check', { simple: true }) !== 'ok') throw new Error('Source integrity_check failed')
if (mode !== 'verify') {
mkdirSync(dirname(output), { recursive: true })
temporary = `${output}.partial-${process.pid}`
// SQLite online backup includes committed WAL pages while the API runs.
await source.backup(temporary)
const check = new Database(temporary, { readonly: true, fileMustExist: true })
try {
if (check.pragma('integrity_check', { simple: true }) !== 'ok') throw new Error('Backup integrity_check failed')
if (check.pragma('foreign_key_check').length) throw new Error('Backup foreign_key_check failed')
} finally { check.close() }
if (mode === 'restore') {
// Only safe after the caller has excluded every process using this volume.
rmSync(`${output}-wal`, { force: true })
rmSync(`${output}-shm`, { force: true })
}
renameSync(temporary, output)
temporary = undefined
}
console.log(JSON.stringify({ mode, input, output, integrity: 'ok' }))
} finally {
source.close()
if (temporary) rmSync(temporary, { force: true })
}