사용자별 credential 저장, lease, projection, runtime 전달과 OpenAI-compatible 계약 및 검증 근거를 함께 반영한다.
75 lines
2.6 KiB
Go
75 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"iop/apps/control-plane/internal/credentialstore"
|
|
)
|
|
|
|
// principalCmd returns the host-local principal management command group.
|
|
// Bootstrap is intentionally CLI-only: it opens the configured packet-01
|
|
// store directly and emits the first raw IOP token exactly once. No remote
|
|
// operation, no credential-bearing wire listener, and no plaintext network
|
|
// activation is added.
|
|
func principalCmd() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "principal",
|
|
Short: "Host-local principal management",
|
|
Long: `Principal commands operate directly on the configured credential
|
|
store without involving the running Control Plane server. They are intended
|
|
for deployment-admin bootstrap only and must never be exposed over the
|
|
plaintext Client WebSocket.`,
|
|
}
|
|
cmd.AddCommand(principalBootstrapCmd())
|
|
return cmd
|
|
}
|
|
|
|
// principalBootstrapCmd issues the first principal and returns its raw IOP
|
|
// token exactly once to stdout. It refuses when any principal already exists.
|
|
// The raw token is never logged or persisted beyond the one-time stdout emit.
|
|
func principalBootstrapCmd() *cobra.Command {
|
|
var alias string
|
|
cmd := &cobra.Command{
|
|
Use: "bootstrap",
|
|
Short: "Issue the first principal and raw token",
|
|
Long: `Open the configured credential store directly and issue the first
|
|
principal. The raw IOP token is written to stdout exactly once and is never
|
|
persisted or logged. If any principal already exists, the command refuses
|
|
and exits with a non-zero status.`,
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
if alias == "" {
|
|
return fmt.Errorf("alias is required; use --alias <name>")
|
|
}
|
|
cfg, err := loadConfig(cfgFile)
|
|
if err != nil {
|
|
return fmt.Errorf("load config: %w", err)
|
|
}
|
|
if cfg.Database.URL == "" {
|
|
return fmt.Errorf("database.url is required for bootstrap")
|
|
}
|
|
ctx := cmd.Context()
|
|
store, err := credentialstore.Open(ctx, cfg.Database.URL)
|
|
if err != nil {
|
|
return fmt.Errorf("open credential store: %w", err)
|
|
}
|
|
defer func() { _ = store.Close() }()
|
|
|
|
issued, err := store.CreateFirstPrincipalWithToken(cmd.Context(), credentialstore.CreatePrincipalInput{Alias: alias})
|
|
if err != nil {
|
|
return fmt.Errorf("create principal: %w", err)
|
|
}
|
|
|
|
// Emit the raw token exactly once to stdout. Nothing else about the
|
|
// raw token is logged, persisted, or returned through any other path.
|
|
if _, err := fmt.Fprintln(cmd.OutOrStdout(), issued.RawToken); err != nil {
|
|
return fmt.Errorf("write raw token: %w", err)
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
cmd.Flags().StringVar(&alias, "alias", "", "human-readable principal alias (required)")
|
|
return cmd
|
|
}
|