@@ -12,7 +12,13 @@ import {
1212 migrateLegacyOrchLayout ,
1313 syncAuthArtifacts
1414} from "../auth-sync.js"
15- import { findAuthorizedKeysSource , resolveAuthorizedKeysPath } from "../path-helpers.js"
15+ import {
16+ defaultProjectsRoot ,
17+ findAuthorizedKeysSource ,
18+ findExistingPath ,
19+ findSshPrivateKey ,
20+ resolveAuthorizedKeysPath
21+ } from "../path-helpers.js"
1622import { withFsPathContext } from "../runtime.js"
1723import { resolvePathFromBase } from "./paths.js"
1824
@@ -40,13 +46,53 @@ const ensureFileReady = (
4046 return "exists"
4147 } )
4248
49+ const appendKeyIfMissing = (
50+ fs : FileSystem . FileSystem ,
51+ resolved : string ,
52+ source : string ,
53+ desiredContents : string
54+ ) : Effect . Effect < void , PlatformError > =>
55+ Effect . gen ( function * ( _ ) {
56+ const currentContents = yield * _ ( fs . readFileString ( resolved ) )
57+ const currentLines = currentContents
58+ . split ( / \r ? \n / )
59+ . map ( ( line ) => line . trim ( ) )
60+ . filter ( ( line ) => line . length > 0 )
61+
62+ if ( currentLines . includes ( desiredContents ) ) {
63+ return
64+ }
65+
66+ const normalizedCurrent = currentContents . trimEnd ( )
67+ const nextContents = normalizedCurrent . length === 0
68+ ? `${ desiredContents } \n`
69+ : `${ normalizedCurrent } \n${ desiredContents } \n`
70+
71+ yield * _ ( fs . writeFileString ( resolved , nextContents ) )
72+ yield * _ ( Effect . log ( `Authorized keys appended from ${ source } to ${ resolved } ` ) )
73+ } )
74+
75+ const resolveAuthorizedKeysSource = (
76+ fs : FileSystem . FileSystem ,
77+ path : Path . Path ,
78+ cwd : string
79+ ) : Effect . Effect < string | null , PlatformError , FileSystem . FileSystem | Path . Path > =>
80+ Effect . gen ( function * ( _ ) {
81+ const sshPrivateKey = yield * _ ( findSshPrivateKey ( fs , path , cwd ) )
82+ const matchingPublicKey = sshPrivateKey === null ? null : yield * _ ( findExistingPath ( fs , `${ sshPrivateKey } .pub` ) )
83+ return matchingPublicKey === null
84+ ? yield * _ ( findAuthorizedKeysSource ( fs , path , cwd ) )
85+ : matchingPublicKey
86+ } )
87+
4388const ensureAuthorizedKeys = (
4489 baseDir : string ,
4590 authorizedKeysPath : string
4691) : Effect . Effect < void , PlatformError , FileSystem . FileSystem | Path . Path > =>
4792 withFsPathContext ( ( { fs, path } ) =>
4893 Effect . gen ( function * ( _ ) {
4994 const resolved = resolveAuthorizedKeysPath ( path , baseDir , authorizedKeysPath )
95+ const managedDefaultAuthorizedKeys = path . join ( defaultProjectsRoot ( process . cwd ( ) ) , "authorized_keys" )
5096 const state = yield * _ (
5197 ensureFileReady (
5298 fs ,
@@ -55,11 +101,8 @@ const ensureAuthorizedKeys = (
55101 `Authorized keys was a directory, moved to ${ backupPath } . Creating a file at ${ resolvedPath } .`
56102 )
57103 )
58- if ( state === "exists" ) {
59- return
60- }
61104
62- const source = yield * _ ( findAuthorizedKeysSource ( fs , path , process . cwd ( ) ) )
105+ const source = yield * _ ( resolveAuthorizedKeysSource ( fs , path , process . cwd ( ) ) )
63106 if ( source === null ) {
64107 yield * _ (
65108 Effect . logError (
@@ -69,6 +112,19 @@ const ensureAuthorizedKeys = (
69112 return
70113 }
71114
115+ const desiredContents = ( yield * _ ( fs . readFileString ( source ) ) ) . trim ( )
116+ if ( desiredContents . length === 0 ) {
117+ yield * _ ( Effect . logWarning ( `Authorized keys source ${ source } is empty. Skipping SSH key sync.` ) )
118+ return
119+ }
120+
121+ if ( state === "exists" ) {
122+ if ( resolved === managedDefaultAuthorizedKeys ) {
123+ yield * _ ( appendKeyIfMissing ( fs , resolved , source , desiredContents ) )
124+ }
125+ return
126+ }
127+
72128 yield * _ ( fs . makeDirectory ( path . dirname ( resolved ) , { recursive : true } ) )
73129 yield * _ ( fs . copyFile ( source , resolved ) )
74130 yield * _ ( Effect . log ( `Authorized keys copied from ${ source } to ${ resolved } ` ) )
0 commit comments