mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-28 03:00:29 -04:00
* improvement(repo): restructuring to make realtime image narrower scoped * improvements * chore(repo): rebase fixes and quality improvements for realtime split Addresses merge-time issues and gaps from the realtime app split: - Retarget stale vi.mock paths to @sim/workflow-persistence/subblocks - Restore README branding, fix AGENTS.md script reference - Restore TSDoc on workflow-persistence subblocks helpers - Use toError() from @sim/utils/errors in save.ts - Add vitest config + local mocks so @sim/audit tests run standalone - Move socket.io-client to devDependencies in apps/realtime - Add missing package COPY steps to docker/app.Dockerfile - Add check:boundaries/check:realtime-prune scripts and wire into CI Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(security): consolidate crypto primitives into @sim/security Move general-purpose crypto primitives out of apps/sim into the @sim/security package so both apps/sim and apps/realtime can share them. @sim/security exports (all pure, dependency-free): ./compare safeCompare (constant-time HMAC-wrapped equality) ./encryption encrypt/decrypt (AES-256-GCM, iv:cipher:tag format) ./hash sha256Hex ./tokens generateSecureToken (base64url) Migrate apps/sim call sites to use these + @sim/utils helpers: crypto.randomUUID() -> generateId() from @sim/utils/id createHash('sha256').digest -> sha256Hex timingSafeEqual on hashed hex -> safeCompare new Promise(setTimeout) -> sleep from @sim/utils/helpers No behavior change: encryption format, digest output, and token length are preserved exactly. * refactor(copilot): use toError in remaining otel/finalize sites Replace the last two `error instanceof Error ? error : new Error(String(error))` patterns with toError from @sim/utils/errors. Completes the sweep of clean candidates — no behavior change. * refactor(security): consolidate HMAC-SHA256 primitives into @sim/security Adds hmacSha256Hex and hmacSha256Base64 to @sim/security/hmac and migrates 15 webhook providers plus 5 other hot paths (deployment token signing, outbound webhook requests, workspace notification delivery, notification test route, Shopify OAuth callback) off bare `createHmac` calls. Secret parameter accepts `string | Buffer` to cover base64-decoded Svix-style secrets (Resend) and MS Teams' HMAC scheme. AWS SigV4 signing in S3 and Textract tools intentionally retains direct `createHmac` usage — its multi-step key derivation chain doesn't fit a generic helper. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(packages): post-audit test + packaging polish - Add safeCompare unit tests (identity, length mismatch, hex-nibble diff). - Add Buffer-secret cases to hmac tests to lock in Svix/MS-Teams contract. - Declare `reactflow` as a peerDependency on @sim/workflow-types — only used for type imports. - Add a barrel export to @sim/workflow-persistence for consumers that prefer package-level imports; subpath exports retained. - Document the data-field invariant in load.ts for loop/parallel subflow patching. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(realtime): address PR review feedback - Remove redundant SOCKET_PORT=3002 env from Dockerfile runner stage (env.PORT already defaults to 3002 via zod schema). - Reorder PORT fallback so an explicitly-set SOCKET_PORT wins over the schema default for PORT; keeps SOCKET_PORT functional as an override instead of dead code. - Add dedicated type-check CI step for @sim/realtime so TS errors surface pre-deploy (the Dockerfile runs source TS via Bun and has no implicit build-time type check). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(realtime): remove unused SOCKET_PORT env var SOCKET_PORT has lived in the socket server since the June 2025 refactor but was never actually set in any deploy config — docker-compose.prod, helm values/templates, .env.example, and docs all use PORT or the 3002 default exclusively. No self-hoster was ever pointed at SOCKET_PORT, so removing it is safe. Simplifies realtime port resolution to `env.PORT` (zod-validated with a 3002 default) and drops the orphaned sim-side schema entry. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Waleed Latif <walif6@gmail.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
68 lines
2.1 KiB
TypeScript
68 lines
2.1 KiB
TypeScript
#!/usr/bin/env bun
|
|
import { mkdtemp, readdir, rm, stat } from 'node:fs/promises'
|
|
import { tmpdir } from 'node:os'
|
|
import path from 'node:path'
|
|
import { $ } from 'bun'
|
|
|
|
const MAX_PRUNED_PACKAGE_COUNT = 25
|
|
|
|
async function listPackages(root: string): Promise<string[]> {
|
|
try {
|
|
const entries = await readdir(root)
|
|
const result: string[] = []
|
|
for (const entry of entries) {
|
|
const full = path.join(root, entry)
|
|
const s = await stat(full)
|
|
if (s.isDirectory()) {
|
|
result.push(entry)
|
|
}
|
|
}
|
|
return result
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
const scratch = await mkdtemp(path.join(tmpdir(), 'sim-realtime-prune-'))
|
|
try {
|
|
console.log(`Pruning @sim/realtime into ${scratch}`)
|
|
await $`bunx turbo prune @sim/realtime --docker --out-dir=${scratch}`.quiet()
|
|
|
|
const apps = await listPackages(path.join(scratch, 'json', 'apps'))
|
|
const packages = await listPackages(path.join(scratch, 'json', 'packages'))
|
|
const total = apps.length + packages.length
|
|
|
|
console.log(`Pruned apps (${apps.length}): ${apps.join(', ') || '(none)'}`)
|
|
console.log(`Pruned packages (${packages.length}): ${packages.join(', ') || '(none)'}`)
|
|
console.log(`Total pruned workspaces: ${total}`)
|
|
|
|
if (total > MAX_PRUNED_PACKAGE_COUNT) {
|
|
console.error(
|
|
`\n❌ Pruned realtime dep graph has ${total} workspaces (limit: ${MAX_PRUNED_PACKAGE_COUNT}).`
|
|
)
|
|
console.error(
|
|
'A new package was pulled into @sim/realtime. Ensure only pure, single-purpose packages are in its dep graph.'
|
|
)
|
|
process.exit(1)
|
|
}
|
|
|
|
const unexpectedApps = apps.filter((name) => name !== 'realtime')
|
|
if (unexpectedApps.length > 0) {
|
|
console.error(
|
|
`\n❌ Pruned realtime tree pulled in unexpected apps/: ${unexpectedApps.join(', ')}`
|
|
)
|
|
process.exit(1)
|
|
}
|
|
|
|
console.log('\n✅ Realtime prune size within expected bounds')
|
|
} finally {
|
|
await rm(scratch, { recursive: true, force: true })
|
|
}
|
|
}
|
|
|
|
void main().catch((error) => {
|
|
console.error('Realtime prune check failed:', error)
|
|
process.exit(1)
|
|
})
|