mirror of
https://github.com/simstudioai/sim.git
synced 2026-04-28 03:00:29 -04:00
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>
This commit is contained in:
7
bun.lock
7
bun.lock
@@ -459,13 +459,14 @@
|
||||
"packages/workflow-types": {
|
||||
"name": "@sim/workflow-types",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"reactflow": "^11.11.4",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sim/tsconfig": "workspace:*",
|
||||
"reactflow": "^11.11.4",
|
||||
"typescript": "^5.7.3",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"reactflow": "^11.11.4",
|
||||
},
|
||||
},
|
||||
},
|
||||
"trustedDependencies": [
|
||||
|
||||
40
packages/security/src/compare.test.ts
Normal file
40
packages/security/src/compare.test.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { safeCompare } from './compare'
|
||||
|
||||
describe('safeCompare', () => {
|
||||
it('returns true for identical strings', () => {
|
||||
expect(safeCompare('abc', 'abc')).toBe(true)
|
||||
})
|
||||
|
||||
it('returns false for equal-length different strings', () => {
|
||||
expect(safeCompare('abc', 'abd')).toBe(false)
|
||||
})
|
||||
|
||||
it('returns false for different-length strings without throwing', () => {
|
||||
expect(safeCompare('short', 'longer-value')).toBe(false)
|
||||
expect(safeCompare('', 'a')).toBe(false)
|
||||
expect(safeCompare('a', '')).toBe(false)
|
||||
})
|
||||
|
||||
it('returns true for two empty strings', () => {
|
||||
expect(safeCompare('', '')).toBe(true)
|
||||
})
|
||||
|
||||
it('handles long inputs', () => {
|
||||
const a = 'x'.repeat(10_000)
|
||||
const b = 'x'.repeat(10_000)
|
||||
expect(safeCompare(a, b)).toBe(true)
|
||||
expect(safeCompare(a, `${b.slice(0, -1)}y`)).toBe(false)
|
||||
})
|
||||
|
||||
it('is case-sensitive', () => {
|
||||
expect(safeCompare('ABC', 'abc')).toBe(false)
|
||||
})
|
||||
|
||||
it('distinguishes hex digests that differ in one nibble', () => {
|
||||
const a = 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7'
|
||||
const b = 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff8'
|
||||
expect(safeCompare(a, b)).toBe(false)
|
||||
expect(safeCompare(a, a)).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -24,6 +24,11 @@ describe('hmacSha256Hex', () => {
|
||||
it('differs when secret changes', () => {
|
||||
expect(hmacSha256Hex('body', 'k1')).not.toBe(hmacSha256Hex('body', 'k2'))
|
||||
})
|
||||
|
||||
it('accepts a Buffer secret and matches the equivalent binary-string secret', () => {
|
||||
const raw = Buffer.from('0b'.repeat(20), 'hex')
|
||||
expect(hmacSha256Hex('Hi There', raw)).toBe(hmacSha256Hex('Hi There', raw.toString('binary')))
|
||||
})
|
||||
})
|
||||
|
||||
describe('hmacSha256Base64', () => {
|
||||
@@ -40,4 +45,11 @@ describe('hmacSha256Base64', () => {
|
||||
const b64 = hmacSha256Base64('body', 'secret')
|
||||
expect(Buffer.from(b64, 'base64').toString('hex')).toBe(hex)
|
||||
})
|
||||
|
||||
it('accepts a Buffer secret (Svix / MS-Teams scheme)', () => {
|
||||
const secret = Buffer.from('whsec-decoded-bytes')
|
||||
const hex = hmacSha256Hex('body', secret)
|
||||
const b64 = hmacSha256Base64('body', secret)
|
||||
expect(Buffer.from(b64, 'base64').toString('hex')).toBe(hex)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./src/index.ts",
|
||||
"default": "./src/index.ts"
|
||||
},
|
||||
"./load": {
|
||||
"types": "./src/load.ts",
|
||||
"default": "./src/load.ts"
|
||||
|
||||
19
packages/workflow-persistence/src/index.ts
Normal file
19
packages/workflow-persistence/src/index.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export {
|
||||
loadWorkflowFromNormalizedTablesRaw,
|
||||
persistMigratedBlocks,
|
||||
type RawNormalizedWorkflow,
|
||||
} from './load'
|
||||
export { saveWorkflowToNormalizedTables } from './save'
|
||||
export {
|
||||
DEFAULT_SUBBLOCK_TYPE,
|
||||
mergeSubBlockValues,
|
||||
mergeSubblockStateWithValues,
|
||||
} from './subblocks'
|
||||
export {
|
||||
convertLoopBlockToLoop,
|
||||
convertParallelBlockToParallel,
|
||||
findChildNodes,
|
||||
generateLoopBlocks,
|
||||
generateParallelBlocks,
|
||||
} from './subflow-helpers'
|
||||
export type { DbOrTx, NormalizedWorkflowData } from './types'
|
||||
@@ -18,6 +18,13 @@ export interface RawNormalizedWorkflow extends NormalizedWorkflowData {
|
||||
* backfill, tool sanitization) depend on the block/tool registry that lives in
|
||||
* the Next app and should not be pulled into leaf services. Callers that want
|
||||
* migrated state should wrap this with their own migration pipeline.
|
||||
*
|
||||
* Invariant: downstream migrations must not mutate `block.data.collection`,
|
||||
* `block.data.whileCondition`, or `block.data.doWhileCondition`. Those fields
|
||||
* are patched here from the subflow config on the pre-migration block, and
|
||||
* callers re-sync only `loop.enabled`/`parallel.enabled` from the migrated
|
||||
* block. If a future migration rewrites these data fields, the loop/parallel
|
||||
* config on the returned object will silently diverge from the migrated block.
|
||||
*/
|
||||
export async function loadWorkflowFromNormalizedTablesRaw(
|
||||
workflowId: string
|
||||
|
||||
@@ -26,11 +26,12 @@
|
||||
"format": "biome format --write .",
|
||||
"format:check": "biome format ."
|
||||
},
|
||||
"dependencies": {
|
||||
"peerDependencies": {
|
||||
"reactflow": "^11.11.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sim/tsconfig": "workspace:*",
|
||||
"reactflow": "^11.11.4",
|
||||
"typescript": "^5.7.3"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user