Skip to content
209 changes: 172 additions & 37 deletions cmd/relayfile-cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6381,6 +6381,7 @@ func runMount(args []string) error {
fs := flag.NewFlagSet("mount", flag.ContinueOnError)
fs.SetOutput(io.Discard)

creds, _ := loadCredentials()
server := fs.String("server", resolveServer("", credentials{}), "relayfile server URL")
token := fs.String("token", strings.TrimSpace(os.Getenv("RELAYFILE_TOKEN")), "bearer token")
credsFile := fs.String("creds-file", strings.TrimSpace(os.Getenv("RELAYFILE_MOUNT_CREDS_FILE")), "delegated relayfile credentials file")
Expand Down Expand Up @@ -6459,8 +6460,11 @@ func runMount(args []string) error {
stateFileProvided := false
stateDirProvided := false
mountKindProvided := false
serverProvided := false
fs.Visit(func(parsed *flag.Flag) {
switch parsed.Name {
case "server":
serverProvided = true
case "local-layout":
localLayoutProvided = true
case "state-file":
Expand All @@ -6487,6 +6491,7 @@ func runMount(args []string) error {
canonicalWorkspaceID := ""
requestedWorkspace := ""
delegatedCredsPath := resolveDelegatedCredentialsPath(*credsFile)
_, delegatedCredsExplicit := explicitDelegatedCredentialsPath(*credsFile)
usesDelegatedWorkspace := false
initialCredExpiresAt := ""
if fs.NArg() > 0 {
Expand All @@ -6495,25 +6500,47 @@ func runMount(args []string) error {
if tokenValue == "" {
bundle, path, berr := loadDelegatedCredentialsForRequest(*credsFile, requestedWorkspace, defaultJoinScopes)
if berr != nil {
return fmt.Errorf("resolve delegated relayfile credentials: %w", berr)
}
delegatedCredsPath = path
bundle, berr = refreshDelegatedCredentials(path, bundle, false)
if berr != nil {
return fmt.Errorf("refresh delegated relayfile credentials: %w", berr)
}
canonicalWorkspaceID = bundle.Workspace()
if requestedWorkspace != "" && !workspaceRequestMatchesDelegatedCredentials(requestedWorkspace, canonicalWorkspaceID) {
return fmt.Errorf(
"relayfile mount without --token uses delegated relayfile workspace %s; pass --token for explicit workspace %q or re-bootstrap delegated credentials for that workspace",
canonicalWorkspaceID,
requestedWorkspace,
)
if delegatedCredsExplicit {
return fmt.Errorf("resolve delegated relayfile credentials: %w", berr)
}
tokenValue = strings.TrimSpace(creds.Token)
Comment on lines 6502 to +6506

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail when an explicit delegated credential file is unusable

When --creds-file or RELAYFILE_MOUNT_CREDS_FILE explicitly selects a missing, malformed, or otherwise unusable delegated bundle and saved login credentials also exist, this branch silently discards the delegated-credential error and mounts with the saved token instead. This violates the explicit credential selection (the standalone mount command treats the credentials file as taking precedence and fails if it cannot be read) and can send setup/mount requests using a token from another workspace or server; only use this fallback when no delegated credentials path was explicitly supplied.

Useful? React with 👍 / 👎.

if tokenValue == "" {
return fmt.Errorf("resolve delegated relayfile credentials: %w", berr)
}
if !serverProvided {
*server = resolveServer("", creds)
}
delegatedCredsPath = ""
} else {
delegatedCredsPath = path
bundle, berr = refreshDelegatedCredentials(path, bundle, false)
if berr != nil {
if delegatedCredsExplicit {
return fmt.Errorf("refresh delegated relayfile credentials: %w", berr)
}
tokenValue = strings.TrimSpace(creds.Token)
if tokenValue == "" {
return fmt.Errorf("refresh delegated relayfile credentials: %w", berr)
}
if !serverProvided {
*server = resolveServer("", creds)
}
delegatedCredsPath = ""
} else {
canonicalWorkspaceID = bundle.Workspace()
if requestedWorkspace != "" && !workspaceRequestMatchesDelegatedCredentials(requestedWorkspace, canonicalWorkspaceID) {
return fmt.Errorf(
"relayfile mount without --token uses delegated relayfile workspace %s; pass --token for explicit workspace %q or re-bootstrap delegated credentials for that workspace",
canonicalWorkspaceID,
requestedWorkspace,
)
}
tokenValue = bundle.BearerToken()
initialCredExpiresAt = bundle.BearerExpiresAt()
*server = strings.TrimRight(bundle.ServerURL(), "/")
usesDelegatedWorkspace = true
}
}
tokenValue = bundle.BearerToken()
initialCredExpiresAt = bundle.BearerExpiresAt()
*server = strings.TrimRight(bundle.ServerURL(), "/")
usesDelegatedWorkspace = true
}
var err error
switch fs.NArg() {
Expand Down Expand Up @@ -7099,20 +7126,43 @@ func prepareWorkspaceCommandClient(workspaceValue, serverFlag, tokenFlag string,
tokenValue := resolveExplicitToken(tokenFlag)
directToken := tokenValue != ""
credsFile := ""
_, delegatedCredsExplicit := explicitDelegatedCredentialsPath("")
var bundle delegatedauth.Bundle
var err error
if !directToken && strings.TrimSpace(tokenValue) == "" {
bundle, credsFile, err = loadOrBootstrapDelegatedCredentials(workspaceValue, requestedScopes)
if err != nil {
return nil, fmt.Errorf("resolve delegated relayfile credentials: %w", err)
if delegatedCredsExplicit {
bundle, credsFile, err = loadDelegatedCredentialsForRequest("", workspaceValue, requestedScopes)
} else {
bundle, credsFile, err = loadOrBootstrapDelegatedCredentials(workspaceValue, requestedScopes)
}
bundle, err = refreshDelegatedCredentials(credsFile, bundle, false)
if err != nil {
return nil, fmt.Errorf("refresh delegated relayfile credentials: %w", err)
}
tokenValue = bundle.BearerToken()
if strings.TrimSpace(serverFlag) == "" {
serverFlag = bundle.ServerURL()
if delegatedCredsExplicit {
return nil, fmt.Errorf("resolve delegated relayfile credentials: %w", err)
}
tokenValue = strings.TrimSpace(creds.Token)
if tokenValue == "" {
return nil, fmt.Errorf("resolve delegated relayfile credentials: %w", err)
}
directToken = true
credsFile = ""
} else {
bundle, err = refreshDelegatedCredentials(credsFile, bundle, false)
if err != nil {
if delegatedCredsExplicit {
return nil, fmt.Errorf("refresh delegated relayfile credentials: %w", err)
}
tokenValue = strings.TrimSpace(creds.Token)
if tokenValue == "" {
return nil, fmt.Errorf("refresh delegated relayfile credentials: %w", err)
}
directToken = true
credsFile = ""
} else {
tokenValue = bundle.BearerToken()
if strings.TrimSpace(serverFlag) == "" {
serverFlag = bundle.ServerURL()
}
}
}
}
workspaceID := ""
Expand Down Expand Up @@ -7181,10 +7231,10 @@ func prepareWorkspaceCommandClient(workspaceValue, serverFlag, tokenFlag string,
}

func workspaceRecordForCommand(workspaceValue, workspaceID string) workspaceRecord {
if record, ok := workspaceRecordByName(strings.TrimSpace(workspaceValue)); ok {
if record, ok := workspaceRecordByID(workspaceID); ok {
return normalizeWorkspaceCommandRecord(record, workspaceID)
}
if record, ok := workspaceRecordByID(workspaceID); ok {
if record, ok := workspaceRecordByName(strings.TrimSpace(workspaceValue)); ok {
return normalizeWorkspaceCommandRecord(record, workspaceID)
}
return workspaceRecord{
Expand Down Expand Up @@ -10591,21 +10641,27 @@ func resolveWorkspaceRecord(nameOrID string) (workspaceRecord, error) {
func resolveWorkspaceIDWithToken(value, token string) (string, error) {
value = strings.TrimSpace(value)
if value != "" {
if id, ok := catalogWorkspaceID(value); ok {
if id, ok, err := catalogWorkspaceIDForRequest(value, token); err != nil {
return "", err
} else if ok {
return id, nil
}
return value, nil
}

if workspaceID := strings.TrimSpace(os.Getenv("RELAYFILE_WORKSPACE")); workspaceID != "" {
if id, ok := catalogWorkspaceID(workspaceID); ok {
if id, ok, err := catalogWorkspaceIDForRequest(workspaceID, token); err != nil {
return "", err
} else if ok {
return id, nil
}
return workspaceID, nil
}

if workspaceID := workspaceIDFromToken(token); workspaceID != "" {
if id, ok := catalogWorkspaceID(workspaceID); ok {
if id, ok, err := catalogWorkspaceIDForRequest(workspaceID, token); err != nil {
return "", err
} else if ok {
return id, nil
}
return workspaceID, nil
Expand All @@ -10621,14 +10677,82 @@ func resolveWorkspaceIDWithToken(value, token string) (string, error) {
}
defaultName := strings.TrimSpace(catalog.Default)
if defaultName != "" {
if id, ok := catalogWorkspaceIDFromCatalog(catalog, defaultName); ok {
if id, ok, err := catalogWorkspaceIDFromCatalogForRequest(catalog, defaultName, token); err != nil {
return "", err
} else if ok {
return id, nil
}
return defaultName, nil
}
return "", errors.New("workspace is required; pass WORKSPACE, set RELAYFILE_WORKSPACE, or run 'agent-relay workspace switch NAME'")
}

func catalogWorkspaceIDForRequest(name, token string) (string, bool, error) {
catalog, err := loadWorkspaceCatalog()
if err != nil {
return "", false, nil
}
return catalogWorkspaceIDFromCatalogForRequest(catalog, name, token)
}

func catalogWorkspaceIDFromCatalogForRequest(catalog workspaceCatalog, name, token string) (string, bool, error) {
name = strings.TrimSpace(name)
if name == "" {
return "", false, nil
}

// An exact ID is already unambiguous, even if another record happens to
// reuse that value as its display name.
for _, workspace := range catalog.Workspaces {
if strings.TrimSpace(workspace.ID) == name {
return name, true, nil
}
}

matches := make([]workspaceRecord, 0, 1)
ids := map[string]struct{}{}
for _, workspace := range catalog.Workspaces {
if strings.TrimSpace(workspace.Name) != name {
continue
}
id := strings.TrimSpace(workspace.ID)
if id == "" {
id = name
}
matches = append(matches, workspace)
ids[id] = struct{}{}
}
if len(ids) == 0 {
return "", false, nil
}
if len(ids) == 1 {
for id := range ids {
return id, true, nil
}
}

tokenWorkspaceID := workspaceIDFromToken(token)
if tokenWorkspaceID != "" {
matchedID := ""
for _, workspace := range matches {
if strings.TrimSpace(workspace.ID) != tokenWorkspaceID && strings.TrimSpace(workspace.RelayWorkspaceID) != tokenWorkspaceID {
continue
}
if matchedID != "" {
return "", false, fmt.Errorf("workspace %q is ambiguous in %s; pass an exact workspace id", name, workspacesPath())
}
matchedID = strings.TrimSpace(workspace.ID)
if matchedID == "" {
matchedID = name
}
}
if matchedID != "" {
return matchedID, true, nil
}
}
return "", false, fmt.Errorf("workspace %q is ambiguous in %s; pass an exact workspace id", name, workspacesPath())
}

func catalogWorkspaceID(name string) (string, bool) {
catalog, err := loadWorkspaceCatalog()
if err != nil {
Expand Down Expand Up @@ -11290,7 +11414,7 @@ func runningMountDaemons(localDir, workspaceID, workspaceName string) ([]mountDa
seen[process.PID] = struct{}{}
}

if pid, verified, strong := verifyDaemonProcessForDiscovery(localDir, workspaceID); pid != 0 {
if pid, verified, strong := verifyDaemonProcessForDiscovery(localDir, workspaceID); pid != 0 && pid != os.Getpid() {
_, foundByScan := seen[pid]
switch {
case !processAlive(pid):
Expand Down Expand Up @@ -11354,6 +11478,11 @@ func mountDaemonCommandMatches(command, localDir, workspaceID, workspaceName str
if !commandHasMountSubcommand(fields) || commandHasOnceFlag(fields) {
return false
}
// `mount --background` is a transient launcher. Only the child carrying
// `--daemonized` serves the mount and should participate in discovery.
if commandHasEnabledBoolFlag(fields, "background") && !commandHasEnabledBoolFlag(fields, "daemonized") {
return false
}
targets := daemonWorkspaceTargets(workspaceID, workspaceName)
if commandMatchesWorkspace(fields, targets) {
return true
Expand Down Expand Up @@ -11386,12 +11515,18 @@ func commandHasMountSubcommand(fields []string) bool {
}

func commandHasOnceFlag(fields []string) bool {
return commandHasEnabledBoolFlag(fields, "once")
}

func commandHasEnabledBoolFlag(fields []string, name string) bool {
longFlag := "--" + name
shortFlag := "-" + name
for _, field := range fields {
if field == "--once" || field == "-once" {
if field == longFlag || field == shortFlag {
return true
}
if strings.HasPrefix(field, "--once=") || strings.HasPrefix(field, "-once=") {
value := strings.TrimSpace(strings.TrimPrefix(strings.TrimPrefix(field, "--once="), "-once="))
if strings.HasPrefix(field, longFlag+"=") || strings.HasPrefix(field, shortFlag+"=") {
value := strings.TrimSpace(strings.TrimPrefix(strings.TrimPrefix(field, longFlag+"="), shortFlag+"="))
if value == "" {
return true
}
Expand Down
Loading
Loading