437aab39b4
P0a1 — Re-architecture Foundation (path resolver + config demotion). Path resolver (REQ-070, R-002): - internal/paths/paths.go: 23 functions for the multi-namespace layout (Root/ClusterDir/NamespaceDir/NS*/DefaultNamespace/CA/MasterKey/CacheDB/ Txn/Peers/KnownHosts/SSH/Server/Config). Honors $ORCA_HOME. 100% coverage. - internal/certpaths/certpaths.go: refactored as thin shim delegating to paths, preserving the v0.8 flat-layout API for backward compat during the dual-write window (REQ-090). Package doc explains the v0.10-P14 migration plan. certpaths deleted after v0.10-P14. 100% coverage. Config demotion (REQ-069, R-014): - internal/config/markdown.go: minimal hand-rolled YAML frontmatter parser (no new dep — yaml.v3 not in go.mod). Returns same *Config struct as HCL. - internal/config/config.go: renamed Load body to LoadHCL (// Deprecated per R-013), added dispatcher Load() routing on extension (.hcl->HCL, .md->Markdown, .yaml->Markdown). Signature preserved so root.go unchanged. - dispatch_test.go + markdown_test.go: 89.8% coverage on config package. Known_hosts flock (REQ-063, deferred P1 from REVIEW_v0.8 A2): - internal/security/flock.go: stdlib syscall.Flock advisory lock helper. - internal/proxmox/bootstrap.go: TOFUHostKeyCallback capture + ResetHostKey both acquire the flock before read-modify-write on known_hosts. Prevents concurrent writers under v0.9 parallel SSH fan-out. 3 flock tests. CA migration spec (grill C-07): - .ciagent/CA_MIGRATION_SPEC_v0.9.md: Option A (preserve trust root, RECOMMENDED) vs Option B (forced re-bootstrap). Pre-flight checks, migration steps, rollback, post-migration invariants, spike plan. Verification: build pass, 17/17 Go packages pass, 20/20 bats pass, gofmt clean, go vet clean, verify-reqs 90 consistent. Coverage: paths 100%, certpaths 100%, config 89.8%, emit covered. ---ci--- project: orca phase: P0a1 milestone: v0.9 status: execute ---/ci---
122 lines
5.0 KiB
Go
122 lines
5.0 KiB
Go
// Package paths resolves on-disk locations for the v0.9 multi-namespace
|
|
// filesystem layout (R-002). It is the canonical source of truth for
|
|
// cluster-wide, per-namespace, and CLI-cache paths.
|
|
//
|
|
// The v0.8 internal/certpaths package is preserved as a thin shim that
|
|
// returns the legacy flat-layout paths during the v0.9 dual-write window
|
|
// (REQ-090). New code should use internal/paths, NOT certpaths.
|
|
package paths
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
const (
|
|
defaultHomeSubdir = ".orca"
|
|
clusterDirName = "cluster"
|
|
defaultNamespace = "_defaults"
|
|
)
|
|
|
|
// Root returns the ORCA home directory. It honors $ORCA_HOME for
|
|
// testability; otherwise it defaults to ~/.orca. An empty $ORCA_HOME is
|
|
// treated as unset.
|
|
func Root() string {
|
|
if p := os.Getenv("ORCA_HOME"); p != "" {
|
|
return p
|
|
}
|
|
home, _ := os.UserHomeDir()
|
|
return filepath.Join(home, defaultHomeSubdir)
|
|
}
|
|
|
|
// ClusterDir returns the cluster-wide directory: Root()/cluster.
|
|
// Cluster-wide artifacts (CA, master key, peers, txns, known_hosts, SSH
|
|
// keys) live here and are NOT scoped to a workload namespace (R-002).
|
|
func ClusterDir() string { return filepath.Join(Root(), clusterDirName) }
|
|
|
|
// NamespaceDir returns the directory for a namespace: Root()/<ns>.
|
|
// Use DefaultNamespace() for the implicit root namespace (R-002 D-159).
|
|
func NamespaceDir(ns string) string { return filepath.Join(Root(), ns) }
|
|
|
|
// NSDb returns the SQLite database path for a namespace:
|
|
// NamespaceDir(ns)/db/orca.db.
|
|
func NSDb(ns string) string { return filepath.Join(NamespaceDir(ns), "db", "orca.db") }
|
|
|
|
// NSEnv returns the .env path for a namespace: NamespaceDir(ns)/.env.
|
|
func NSEnv(ns string) string { return filepath.Join(NamespaceDir(ns), ".env") }
|
|
|
|
// NSSecrets returns the encrypted secrets env path for a namespace:
|
|
// NamespaceDir(ns)/.env.secrets.
|
|
func NSSecrets(ns string) string { return filepath.Join(NamespaceDir(ns), ".env.secrets") }
|
|
|
|
// NSJobs returns the jobs directory for a namespace: NamespaceDir(ns)/jobs.
|
|
func NSJobs(ns string) string { return filepath.Join(NamespaceDir(ns), "jobs") }
|
|
|
|
// NSAlloc returns the allocation directory for a namespace:
|
|
// NamespaceDir(ns)/alloc.
|
|
func NSAlloc(ns string) string { return filepath.Join(NamespaceDir(ns), "alloc") }
|
|
|
|
// NSMd returns the namespace Markdown doc path (R-014):
|
|
// NamespaceDir(ns)/ns.md.
|
|
func NSMd(ns string) string { return filepath.Join(NamespaceDir(ns), "ns.md") }
|
|
|
|
// DefaultNamespace returns the implicit root namespace name (R-002 D-159).
|
|
func DefaultNamespace() string { return defaultNamespace }
|
|
|
|
// CACertPath returns the v0.9 cluster CA cert path:
|
|
// ClusterDir()/ca.crt (D-101). The v0.8 internal CA still writes to
|
|
// Root()/ca.crt; the move happens in v0.10-P14.
|
|
func CACertPath() string { return filepath.Join(ClusterDir(), "ca.crt") }
|
|
|
|
// CAKeyPath returns the v0.9 cluster CA key path:
|
|
// ClusterDir()/ca.key.
|
|
func CAKeyPath() string { return filepath.Join(ClusterDir(), "ca.key") }
|
|
|
|
// MasterKeyPath returns the AES-256-GCM root master key path
|
|
// (R-011, mode 0600): ClusterDir()/master.key. Not generated until
|
|
// v0.10-P03.
|
|
func MasterKeyPath() string { return filepath.Join(ClusterDir(), "master.key") }
|
|
|
|
// CacheDB returns the CLI-side cache database path (R-008):
|
|
// Root()/orca_cache.db. Not created until v0.9-P0a2.
|
|
func CacheDB() string { return filepath.Join(Root(), "orca_cache.db") }
|
|
|
|
// TxnDir returns the cluster transaction log directory (R-016):
|
|
// ClusterDir()/txns.
|
|
func TxnDir() string { return filepath.Join(ClusterDir(), "txns") }
|
|
|
|
// PeersDir returns the cluster peers directory: ClusterDir()/peers.
|
|
func PeersDir() string { return filepath.Join(ClusterDir(), "peers") }
|
|
|
|
// PeerDir returns the directory for a single peer host:
|
|
// PeersDir()/host.
|
|
func PeerDir(host string) string { return filepath.Join(PeersDir(), host) }
|
|
|
|
// KnownHostsPath returns the SSH known_hosts path (D-035):
|
|
// ClusterDir()/known_hosts.
|
|
func KnownHostsPath() string { return filepath.Join(ClusterDir(), "known_hosts") }
|
|
|
|
// SSHKeyPath returns the orca SSH private key path:
|
|
// ClusterDir()/orca_ssh_key (D-037).
|
|
func SSHKeyPath() string { return filepath.Join(ClusterDir(), "orca_ssh_key") }
|
|
|
|
// SSHPubPath returns the orca SSH public key path:
|
|
// ClusterDir()/orca_ssh_key.pub.
|
|
func SSHPubPath() string { return filepath.Join(ClusterDir(), "orca_ssh_key.pub") }
|
|
|
|
// ServerCertPath returns the legacy server cert path (legacy compat):
|
|
// ClusterDir()/server.crt. step-ca will replace this in a later phase.
|
|
func ServerCertPath() string { return filepath.Join(ClusterDir(), "server.crt") }
|
|
|
|
// ServerKeyPath returns the legacy server key path (legacy compat):
|
|
// ClusterDir()/server.key. step-ca will replace this in a later phase.
|
|
func ServerKeyPath() string { return filepath.Join(ClusterDir(), "server.key") }
|
|
|
|
// ConfigPath returns the new Markdown-frontmatter config path (R-014):
|
|
// ClusterDir()/config.md. The legacy HCL path is ClusterDir()/config.hcl.
|
|
func ConfigPath() string { return filepath.Join(ClusterDir(), "config.md") }
|
|
|
|
// LegacyHCLConfigPath returns the legacy HCL config path:
|
|
// ClusterDir()/config.hcl.
|
|
func LegacyHCLConfigPath() string { return filepath.Join(ClusterDir(), "config.hcl") }
|