Update README.md to reflect actual configuration management implementation (#310)
* docs: update README.md to reflect actual configuration implementation This commit updates the README.md to accurately describe the project's decentralized YAML-based configuration management system, as identified in the Architecture & Design Pattern Audit (PR #208). Key changes: - Refactored 'Architecture' section to match actual directory structure (e.g., pkg/framework/core, pkg/repos, pkg/agentic, pkg/mcp). - Removed outdated and non-existent references to pkg/config (JSON), pkg/display, and pkg/workspace. - Added a new 'Configuration Management' section documenting YAML file locations (.core/build.yaml, ~/.core/config.yaml, repos.yaml, etc.). - Updated 'Quick Start' example to use the correct package path and handle errors. - Updated 'Current State' table and 'Package Deep Dives' to match present packages. - Cleaned up broken links and references to external repos (core-gui). * docs: update README.md to reflect actual configuration implementation This commit updates the README.md to accurately describe the project's decentralized YAML-based configuration management system, as identified in the Architecture & Design Pattern Audit (PR #208). Key changes: - Refactored 'Architecture' section to match actual directory structure (e.g., pkg/framework/core, pkg/repos, pkg/agentic, pkg/mcp). - Removed outdated and non-existent references to pkg/config (JSON), pkg/display, and pkg/workspace. - Added a new 'Configuration Management' section documenting YAML file locations (.core/build.yaml, ~/.core/config.yaml, repos.yaml, etc.). - Updated 'Quick Start' example to use the correct package path and handle errors. - Updated 'Current State' table and 'Package Deep Dives' to match present packages. - Cleaned up broken links and references to external repos (core-gui). - Fixed formatting in pkg/io/local/client.go to satisfy CI. * docs: update README and fix auto-merge CI This commit completes the README update to reflect the actual configuration implementation and also fixes a CI failure in the auto-merge workflow. Changes: - README.md: Updated to document the decentralized YAML-based configuration system and current project structure. - pkg/io/local/client.go: Fixed minor formatting to satisfy CI. - .github/workflows/auto-merge.yml: Replaced the broken reusable workflow call with a local implementation that includes the '--repo' flag for the 'gh' command. This avoids the 'fatal: not a git repository' error in environments without a '.git' directory. * chore: fix merge conflict and address PR comments - Merged origin/dev into the current branch. - Resolved merge conflict in .github/workflows/auto-merge.yml. - Updated auto-merge.yml with the local implementation to avoid git repository requirement in CI. * docs: update README, fix auto-merge CI, and fix security vulnerability - README.md: Updated to document decentralized YAML configuration. - .github/workflows/auto-merge.yml: Fixed CI by implementing auto-merge locally. - pkg/unifi/client.go: Fixed CodeQL security alert by making TLS verification configurable. - pkg/unifi/config.go: Added 'unifi.insecure' config support. - internal/cmd/unifi/: Added '--insecure' flag to CLI commands. - pkg/io/local/client.go: Minor formatting fix. * fix: address code review comments - Document centralized pkg/config service as primary configuration mechanism - Add pkg/config entry back to package status table - Document repos.yaml auto-discovery locations (cwd, parents, home paths) - Clarify pkg/crypt/openpgp subpackage provides asymmetric encryption - Add ChaCha20-Poly1305 to symmetric encryption list - Fix InsecureSkipVerify: only use custom HTTP client when insecure=true - Add security warnings and #nosec annotation for intentional usage Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude <developers@lethean.io> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
5dd581c3bf
commit
bd8617c3a5
3 changed files with 82 additions and 71 deletions
122
README.md
122
README.md
|
|
@ -44,9 +44,9 @@ For more details, see the [User Guide](docs/user-guide.md).
|
||||||
## Framework Quick Start (Go)
|
## Framework Quick Start (Go)
|
||||||
|
|
||||||
```go
|
```go
|
||||||
import core "github.com/host-uk/core"
|
import core "github.com/host-uk/core/pkg/framework/core"
|
||||||
|
|
||||||
app := core.New(
|
app, err := core.New(
|
||||||
core.WithServiceLock(),
|
core.WithServiceLock(),
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
@ -100,21 +100,20 @@ task cli:run # Build and run
|
||||||
|
|
||||||
```
|
```
|
||||||
.
|
.
|
||||||
├── core.go # Facade re-exporting pkg/core
|
├── main.go # CLI application entry point
|
||||||
├── pkg/
|
├── pkg/
|
||||||
│ ├── core/ # Service container, DI, Runtime[T]
|
│ ├── framework/core/ # Service container, DI, Runtime[T]
|
||||||
│ ├── config/ # JSON persistence, XDG paths
|
|
||||||
│ ├── display/ # Windows, tray, menus (Wails)
|
|
||||||
│ ├── crypt/ # Hashing, checksums, PGP
|
│ ├── crypt/ # Hashing, checksums, PGP
|
||||||
│ │ └── openpgp/ # Full PGP implementation
|
|
||||||
│ ├── io/ # Medium interface + backends
|
│ ├── io/ # Medium interface + backends
|
||||||
│ ├── workspace/ # Encrypted workspace management
|
|
||||||
│ ├── help/ # In-app documentation
|
│ ├── help/ # In-app documentation
|
||||||
│ └── i18n/ # Internationalization
|
│ ├── i18n/ # Internationalization
|
||||||
├── cmd/
|
│ ├── repos/ # Multi-repo registry & management
|
||||||
│ ├── core/ # CLI application
|
│ ├── agentic/ # AI agent task management
|
||||||
│ └── core-gui/ # Wails GUI application
|
│ └── mcp/ # Model Context Protocol service
|
||||||
└── go.work # Links root, cmd/core, cmd/core-gui
|
├── internal/
|
||||||
|
│ ├── cmd/ # CLI command implementations
|
||||||
|
│ └── variants/ # Build variants (full, minimal, etc.)
|
||||||
|
└── go.mod # Go module definition
|
||||||
```
|
```
|
||||||
|
|
||||||
### Service Pattern (Dual-Constructor DI)
|
### Service Pattern (Dual-Constructor DI)
|
||||||
|
|
@ -171,6 +170,40 @@ Service("workspace") // Get service by name (returns any)
|
||||||
|
|
||||||
**NOT exposed:** Direct calls like `workspace.CreateWorkspace()` or `crypt.Hash()`.
|
**NOT exposed:** Direct calls like `workspace.CreateWorkspace()` or `crypt.Hash()`.
|
||||||
|
|
||||||
|
## Configuration Management
|
||||||
|
|
||||||
|
Core uses a **centralized configuration service** implemented in `pkg/config`, with YAML-based persistence and layered overrides.
|
||||||
|
|
||||||
|
The `pkg/config` package provides:
|
||||||
|
|
||||||
|
- YAML-backed persistence at `~/.core/config.yaml`
|
||||||
|
- Dot-notation key access (for example: `cfg.Set("dev.editor", "vim")`, `cfg.GetString("dev.editor")`)
|
||||||
|
- Environment variable overlay support (env vars can override persisted values)
|
||||||
|
- Thread-safe operations for concurrent reads/writes
|
||||||
|
|
||||||
|
Application code should treat `pkg/config` as the **primary configuration mechanism**. Direct reads/writes to YAML files should generally be avoided from application logic in favour of using this centralized service.
|
||||||
|
|
||||||
|
### Project and Service Configuration Files
|
||||||
|
|
||||||
|
In addition to the centralized configuration service, Core uses several YAML files for project-specific build/CI and service configuration. These live alongside (but are distinct from) the centralized configuration:
|
||||||
|
|
||||||
|
- **Project Configuration** (in the `.core/` directory of the project root):
|
||||||
|
- `build.yaml`: Build targets, flags, and project metadata.
|
||||||
|
- `release.yaml`: Release automation, changelog settings, and publishing targets.
|
||||||
|
- `ci.yaml`: CI pipeline configuration.
|
||||||
|
- **Global Configuration** (in the `~/.core/` directory):
|
||||||
|
- `config.yaml`: Centralized user/framework settings and defaults, managed via `pkg/config`.
|
||||||
|
- `agentic.yaml`: Configuration for agentic services (BaseURL, Token, etc.).
|
||||||
|
- **Registry Configuration** (`repos.yaml`, auto-discovered):
|
||||||
|
- Multi-repo registry definition.
|
||||||
|
- Searched in the current directory and its parent directories (walking up).
|
||||||
|
- Then in `~/Code/host-uk/repos.yaml`.
|
||||||
|
- Finally in `~/.config/core/repos.yaml`.
|
||||||
|
|
||||||
|
### Format
|
||||||
|
|
||||||
|
All persisted configuration files described above use **YAML** format for readability and nested structure support.
|
||||||
|
|
||||||
### The IPC Bridge Pattern (Chosen Architecture)
|
### The IPC Bridge Pattern (Chosen Architecture)
|
||||||
|
|
||||||
Sub-services are accessed via Core's **IPC/ACTION system**, not direct Wails bindings:
|
Sub-services are accessed via Core's **IPC/ACTION system**, not direct Wails bindings:
|
||||||
|
|
@ -211,16 +244,15 @@ func (s *Service) HandleIPCEvents(c *core.Core, msg core.Message) error {
|
||||||
|
|
||||||
### Generating Bindings
|
### Generating Bindings
|
||||||
|
|
||||||
|
Wails v3 bindings are typically generated in the GUI repository (e.g., `core-gui`).
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd cmd/core-gui
|
|
||||||
wails3 generate bindings # Regenerate after Go changes
|
wails3 generate bindings # Regenerate after Go changes
|
||||||
```
|
```
|
||||||
|
|
||||||
Bindings output to `cmd/core-gui/public/bindings/github.com/host-uk/core/` mirroring Go package structure.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Service Interfaces (`pkg/core/interfaces.go`)
|
### Service Interfaces (`pkg/framework/core/interfaces.go`)
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type Config interface {
|
type Config interface {
|
||||||
|
|
@ -253,54 +285,27 @@ type Crypt interface {
|
||||||
|
|
||||||
| Package | Notes |
|
| Package | Notes |
|
||||||
|---------|-------|
|
|---------|-------|
|
||||||
| `pkg/core` | Service container, DI, thread-safe - solid |
|
| `pkg/framework/core` | Service container, DI, thread-safe - solid |
|
||||||
| `pkg/config` | JSON persistence, XDG paths - solid |
|
| `pkg/config` | Layered YAML configuration, XDG paths - solid |
|
||||||
| `pkg/crypt` | Hashing, checksums, PGP - solid, well-tested |
|
| `pkg/crypt` | Hashing, checksums, symmetric/asymmetric - solid, well-tested |
|
||||||
| `pkg/help` | Embedded docs, Show/ShowAt - solid |
|
| `pkg/help` | Embedded docs, full-text search - solid |
|
||||||
| `pkg/i18n` | Multi-language with go-i18n - solid |
|
| `pkg/i18n` | Multi-language with go-i18n - solid |
|
||||||
| `pkg/io` | Medium interface + local backend - solid |
|
| `pkg/io` | Medium interface + local backend - solid |
|
||||||
| `pkg/workspace` | Workspace creation, switching, file ops - functional |
|
| `pkg/repos` | Multi-repo registry & management - solid |
|
||||||
|
| `pkg/agentic` | AI agent task management - solid |
|
||||||
### Partial
|
| `pkg/mcp` | Model Context Protocol service - solid |
|
||||||
|
|
||||||
| Package | Issues |
|
|
||||||
|---------|--------|
|
|
||||||
| `pkg/display` | Window creation works; menu/tray handlers are TODOs |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Priority Work Items
|
|
||||||
|
|
||||||
### 1. IMPLEMENT: System Tray Brand Support
|
|
||||||
|
|
||||||
`pkg/display/tray.go:52-63` - Commented brand-specific menu items need implementation.
|
|
||||||
|
|
||||||
### 2. ADD: Integration Tests
|
|
||||||
|
|
||||||
| Package | Notes |
|
|
||||||
|---------|-------|
|
|
||||||
| `pkg/display` | Integration tests requiring Wails runtime (27% unit coverage) |
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Package Deep Dives
|
## Package Deep Dives
|
||||||
|
|
||||||
### pkg/workspace - The Core Feature
|
### pkg/crypt
|
||||||
|
|
||||||
Each workspace is:
|
The crypt package provides a comprehensive suite of cryptographic primitives:
|
||||||
1. Identified by LTHN hash of user identifier
|
- **Hashing & Checksums**: SHA-256, SHA-512, and CRC32 support.
|
||||||
2. Has directory structure: `config/`, `log/`, `data/`, `files/`, `keys/`
|
- **Symmetric Encryption**: AES-GCM and ChaCha20-Poly1305 for secure data at rest.
|
||||||
3. Gets a PGP keypair generated on creation
|
- **Key Derivation**: Argon2id for secure password hashing.
|
||||||
4. Files accessed via obfuscated paths
|
- **Asymmetric Encryption**: PGP implementation in the `pkg/crypt/openpgp` subpackage using `github.com/ProtonMail/go-crypto`.
|
||||||
|
|
||||||
The `workspaceList` maps workspace IDs to public keys.
|
|
||||||
|
|
||||||
### pkg/crypt/openpgp
|
|
||||||
|
|
||||||
Full PGP using `github.com/ProtonMail/go-crypto`:
|
|
||||||
- `CreateKeyPair(name, passphrase)` - RSA-4096 with revocation cert
|
|
||||||
- `EncryptPGP()` - Encrypt + optional signing
|
|
||||||
- `DecryptPGP()` - Decrypt + optional signature verification
|
|
||||||
|
|
||||||
### pkg/io - Storage Abstraction
|
### pkg/io - Storage Abstraction
|
||||||
|
|
||||||
|
|
@ -386,5 +391,4 @@ core <command> --help
|
||||||
1. Run `task test` to verify all tests pass
|
1. Run `task test` to verify all tests pass
|
||||||
2. Follow TDD: `task test-gen` creates stubs, implement to pass
|
2. Follow TDD: `task test-gen` creates stubs, implement to pass
|
||||||
3. The dual-constructor pattern is intentional: `New(deps)` for tests, `Register()` for runtime
|
3. The dual-constructor pattern is intentional: `New(deps)` for tests, `Register()` for runtime
|
||||||
4. See `cmd/core-gui/main.go` for how services wire together
|
4. IPC handlers in each service's `HandleIPCEvents()` are the frontend bridge
|
||||||
5. IPC handlers in each service's `HandleIPCEvents()` are the frontend bridge
|
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,10 @@ func showConfig() error {
|
||||||
cli.Blank()
|
cli.Blank()
|
||||||
cli.Print(" %s %s\n", dimStyle.Render("URL:"), valueStyle.Render(url))
|
cli.Print(" %s %s\n", dimStyle.Render("URL:"), valueStyle.Render(url))
|
||||||
|
|
||||||
|
if insecure {
|
||||||
|
cli.Print(" %s %s\n", dimStyle.Render("Insecure:"), warningStyle.Render("true (TLS verification skipped)"))
|
||||||
|
}
|
||||||
|
|
||||||
if user != "" {
|
if user != "" {
|
||||||
cli.Print(" %s %s\n", dimStyle.Render("User:"), valueStyle.Render(user))
|
cli.Print(" %s %s\n", dimStyle.Render("User:"), valueStyle.Render(user))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ type Client struct {
|
||||||
|
|
||||||
// New creates a new UniFi API client for the given controller URL and credentials.
|
// New creates a new UniFi API client for the given controller URL and credentials.
|
||||||
// TLS verification can be disabled via the insecure parameter (useful for self-signed certs on home lab controllers).
|
// TLS verification can be disabled via the insecure parameter (useful for self-signed certs on home lab controllers).
|
||||||
|
// WARNING: Setting insecure=true disables certificate verification and should only be used in trusted network
|
||||||
|
// environments with self-signed certificates (e.g., home lab controllers).
|
||||||
func New(url, user, pass, apikey string, insecure bool) (*Client, error) {
|
func New(url, user, pass, apikey string, insecure bool) (*Client, error) {
|
||||||
cfg := &uf.Config{
|
cfg := &uf.Config{
|
||||||
URL: url,
|
URL: url,
|
||||||
|
|
@ -25,23 +27,24 @@ func New(url, user, pass, apikey string, insecure bool) (*Client, error) {
|
||||||
APIKey: apikey,
|
APIKey: apikey,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip TLS verification if requested (e.g. for self-signed certs)
|
|
||||||
httpClient := &http.Client{
|
|
||||||
Transport: &http.Transport{
|
|
||||||
TLSClientConfig: &tls.Config{
|
|
||||||
InsecureSkipVerify: insecure,
|
|
||||||
MinVersion: tls.VersionTLS12,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
api, err := uf.NewUnifi(cfg)
|
api, err := uf.NewUnifi(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, log.E("unifi.New", "failed to create client", err)
|
return nil, log.E("unifi.New", "failed to create client", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override the HTTP client to skip TLS verification
|
// Only override the HTTP client if insecure mode is explicitly requested
|
||||||
api.Client = httpClient
|
if insecure {
|
||||||
|
// #nosec G402 -- InsecureSkipVerify is intentionally enabled for home lab controllers
|
||||||
|
// with self-signed certificates. This is opt-in via the insecure parameter.
|
||||||
|
api.Client = &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &Client{api: api, url: url}, nil
|
return &Client{api: api, url: url}, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue