/ services / teamMemorySync / teamMemSecretGuard.ts
teamMemSecretGuard.ts
 1  import { feature } from 'bun:bundle'
 2  
 3  /**
 4   * Check if a file write/edit to a team memory path contains secrets.
 5   * Returns an error message if secrets are detected, or null if safe.
 6   *
 7   * This is called from FileWriteTool and FileEditTool validateInput to
 8   * prevent the model from writing secrets into team memory files, which
 9   * would be synced to all repository collaborators.
10   *
11   * Callers can import and call this unconditionally — the internal
12   * feature('TEAMMEM') guard keeps it inert when the build flag is off.
13   * secretScanner assembles sensitive prefixes at runtime (ANT_KEY_PFX).
14   */
15  export function checkTeamMemSecrets(
16    filePath: string,
17    content: string,
18  ): string | null {
19    if (feature('TEAMMEM')) {
20      /* eslint-disable @typescript-eslint/no-require-imports */
21      const { isTeamMemPath } =
22        require('../../memdir/teamMemPaths.js') as typeof import('../../memdir/teamMemPaths.js')
23      const { scanForSecrets } =
24        require('./secretScanner.js') as typeof import('./secretScanner.js')
25      /* eslint-enable @typescript-eslint/no-require-imports */
26  
27      if (!isTeamMemPath(filePath)) {
28        return null
29      }
30  
31      const matches = scanForSecrets(content)
32      if (matches.length === 0) {
33        return null
34      }
35  
36      const labels = matches.map(m => m.label).join(', ')
37      return (
38        `Content contains potential secrets (${labels}) and cannot be written to team memory. ` +
39        'Team memory is shared with all repository collaborators. ' +
40        'Remove the sensitive content and try again.'
41      )
42    }
43    return null
44  }