mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-21 04:27:22 +08:00
improvement(repo): separate realtime into separate app (#4262)
* 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>
This commit is contained in:
co-authored by
Claude Opus 4.7
Waleed Latif
parent
bed5e95742
commit
5f0f0edd63
@@ -1,7 +1,7 @@
|
||||
import { vi } from 'vitest'
|
||||
|
||||
/**
|
||||
* Controllable mock functions for `@/lib/audit/log`.
|
||||
* Controllable mock functions for `@sim/audit`.
|
||||
* Exposes `mockRecordAudit` so tests can assert or override behavior per test.
|
||||
*
|
||||
* @example
|
||||
@@ -17,11 +17,11 @@ export const auditMockFns = {
|
||||
}
|
||||
|
||||
/**
|
||||
* Static mock module for `@/lib/audit/log`.
|
||||
* Static mock module for `@sim/audit`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* vi.mock('@/lib/audit/log', () => auditMock)
|
||||
* vi.mock('@sim/audit', () => auditMock)
|
||||
* ```
|
||||
*/
|
||||
export const auditMock = {
|
||||
|
||||
@@ -120,6 +120,8 @@ export {
|
||||
export { telemetryMock } from './telemetry.mock'
|
||||
// URL mocks
|
||||
export { urlsMock, urlsMockFns } from './urls.mock'
|
||||
// Workflow authz package mocks (for @sim/workflow-authz)
|
||||
export { workflowAuthzMock, workflowAuthzMockFns } from './workflow-authz.mock'
|
||||
// Workflows API utils mocks (for @/app/api/workflows/utils)
|
||||
export { workflowsApiUtilsMock, workflowsApiUtilsMockFns } from './workflows-api-utils.mock'
|
||||
// Workflows orchestration mocks (for @/lib/workflows/orchestration)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { vi } from 'vitest'
|
||||
|
||||
/**
|
||||
* Controllable mocks for the `@sim/workflow-authz` package.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { workflowAuthzMockFns } from '@sim/testing'
|
||||
*
|
||||
* workflowAuthzMockFns.mockAuthorizeWorkflowByWorkspacePermission.mockResolvedValue({
|
||||
* allowed: true,
|
||||
* status: 200,
|
||||
* workflow: { id: 'wf-1' },
|
||||
* workspacePermission: 'admin',
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
export const workflowAuthzMockFns = {
|
||||
mockAuthorizeWorkflowByWorkspacePermission: vi.fn(),
|
||||
mockGetActiveWorkflowContext: vi.fn(),
|
||||
mockGetActiveWorkflowRecord: vi.fn(),
|
||||
mockAssertActiveWorkflowContext: vi.fn(),
|
||||
}
|
||||
|
||||
/**
|
||||
* Static mock module for `@sim/workflow-authz`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* vi.mock('@sim/workflow-authz', () => workflowAuthzMock)
|
||||
* ```
|
||||
*/
|
||||
export const workflowAuthzMock = {
|
||||
authorizeWorkflowByWorkspacePermission:
|
||||
workflowAuthzMockFns.mockAuthorizeWorkflowByWorkspacePermission,
|
||||
getActiveWorkflowContext: workflowAuthzMockFns.mockGetActiveWorkflowContext,
|
||||
getActiveWorkflowRecord: workflowAuthzMockFns.mockGetActiveWorkflowRecord,
|
||||
assertActiveWorkflowContext: workflowAuthzMockFns.mockAssertActiveWorkflowContext,
|
||||
}
|
||||
@@ -20,7 +20,6 @@ export const workflowsUtilsMockFns = {
|
||||
mockWorkflowHasResponseBlock: vi.fn(),
|
||||
mockCreateHttpResponseFromBlock: vi.fn(),
|
||||
mockValidateWorkflowPermissions: vi.fn(),
|
||||
mockAuthorizeWorkflowByWorkspacePermission: vi.fn(),
|
||||
mockCreateWorkflowRecord: vi.fn(),
|
||||
mockUpdateWorkflowRecord: vi.fn(),
|
||||
mockDeleteWorkflowRecord: vi.fn(),
|
||||
@@ -38,10 +37,12 @@ export const workflowsUtilsMockFns = {
|
||||
*
|
||||
* Default behaviors:
|
||||
* - `getWorkflowById` resolves to `null`
|
||||
* - `authorizeWorkflowByWorkspacePermission` resolves to allowed with `test-workspace-id`
|
||||
* - `validateWorkflowPermissions` resolves to an authorized result
|
||||
* - Other functions resolve to sensible empty/success defaults
|
||||
*
|
||||
* `authorizeWorkflowByWorkspacePermission` moved to `@sim/workflow-authz`;
|
||||
* use `workflowAuthzMock` / `workflowAuthzMockFns` for that surface.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* vi.mock('@/lib/workflows/utils', () => workflowsUtilsMock)
|
||||
@@ -56,8 +57,6 @@ export const workflowsUtilsMock = {
|
||||
workflowHasResponseBlock: workflowsUtilsMockFns.mockWorkflowHasResponseBlock,
|
||||
createHttpResponseFromBlock: workflowsUtilsMockFns.mockCreateHttpResponseFromBlock,
|
||||
validateWorkflowPermissions: workflowsUtilsMockFns.mockValidateWorkflowPermissions,
|
||||
authorizeWorkflowByWorkspacePermission:
|
||||
workflowsUtilsMockFns.mockAuthorizeWorkflowByWorkspacePermission,
|
||||
createWorkflowRecord: workflowsUtilsMockFns.mockCreateWorkflowRecord,
|
||||
updateWorkflowRecord: workflowsUtilsMockFns.mockUpdateWorkflowRecord,
|
||||
deleteWorkflowRecord: workflowsUtilsMockFns.mockDeleteWorkflowRecord,
|
||||
|
||||
Reference in New Issue
Block a user