From cd3971a5584f36bc36eca55ecb7b1cd0904a58c2 Mon Sep 17 00:00:00 2001 From: be-coder-07 Date: Wed, 5 Aug 2026 13:32:34 -0500 Subject: [PATCH] fix(mosaic): exclude nested secret migration paths --- packages/mosaic/src/commands/brain-store.spec.ts | 12 +++++++++++- packages/mosaic/src/commands/brain-store.ts | 12 ++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/mosaic/src/commands/brain-store.spec.ts b/packages/mosaic/src/commands/brain-store.spec.ts index abd488be..9d39f7ad 100644 --- a/packages/mosaic/src/commands/brain-store.spec.ts +++ b/packages/mosaic/src/commands/brain-store.spec.ts @@ -658,6 +658,15 @@ describe('R7 — migration is non-destructive, append-only, and explicit', (): v for (const name of secretNames) { writeFileSync(join(laneRoot, name), 'DO-NOT-MIGRATE\n'); } + const nestedSecretPaths = [ + join('.env.d', 'database.txt'), + join('credentials.d', 'token.txt'), + join('secrets', 'private.txt'), + ]; + for (const path of nestedSecretPaths) { + mkdirSync(join(laneRoot, path, '..'), { recursive: true }); + writeFileSync(join(laneRoot, path), 'NESTED-SECRET-MARKER\n'); + } const plan = sut.discoverBrainMigration( { sourceRoot, brainRoot, seat: 'seat-a', lane: 'lane-a', laneActive: true }, @@ -666,8 +675,9 @@ describe('R7 — migration is non-destructive, append-only, and explicit', (): v expect(plan.status).toBe('ready'); expect(plan.candidates).toHaveLength(0); - expect(plan.reported).toHaveLength(secretNames.length); + expect(plan.reported).toHaveLength(secretNames.length + nestedSecretPaths.length); expect(plan.reported.every((entry) => /secret/i.test(entry.reason))).toBe(true); + expect(JSON.stringify(plan)).not.toContain('NESTED-SECRET-MARKER'); expect(existsSync(brainRoot)).toBe(false); }); diff --git a/packages/mosaic/src/commands/brain-store.ts b/packages/mosaic/src/commands/brain-store.ts index 875cc3c7..6a45f5a1 100644 --- a/packages/mosaic/src/commands/brain-store.ts +++ b/packages/mosaic/src/commands/brain-store.ts @@ -630,8 +630,8 @@ function migrationCandidate( }; } -function secretShapedPath(path: string): boolean { - const name = basename(path).toLowerCase(); +function secretShapedName(value: string): boolean { + const name = value.toLowerCase(); return ( name === '.env' || name.startsWith('.env.') || @@ -648,6 +648,10 @@ function secretShapedPath(path: string): boolean { ); } +function secretShapedPath(sourceRoot: string, path: string): boolean { + return relative(sourceRoot, path).split(sep).filter(Boolean).some(secretShapedName); +} + function reportAll(paths: readonly string[], reason: string): MigrationReport[] { return paths.map((path: string): MigrationReport => ({ path, reason })); } @@ -708,7 +712,7 @@ export function discoverBrainMigration( 'Ownership or supported migration shape was not established; retained and reported.', ); for (const path of laneFiles) { - if (secretShapedPath(path)) { + if (secretShapedPath(input.sourceRoot, path)) { reported.push({ path, reason: 'Secret-shaped state is forbidden in the brain; retained and reported.', @@ -724,7 +728,7 @@ export function discoverBrainMigration( } } for (const path of seatFiles) { - if (secretShapedPath(path)) { + if (secretShapedPath(input.sourceRoot, path)) { reported.push({ path, reason: 'Secret-shaped state is forbidden in the brain; retained and reported.',