Add User Documentation (User Guide, FAQ, Troubleshooting) (#307)

* docs: add user guide, faq, and enhance troubleshooting

- Created docs/user-guide.md with key concepts and workflows.
- Created docs/faq.md with common questions and answers.
- Enhanced docs/troubleshooting.md with AI/Agentic issues.
- Updated README.md with CLI Quick Start and Getting Help sections.
- Refactored mkdocs.yml to reflect actual file structure and include new docs.

* docs: add user documentation and fix mkdocs navigation

- Created docs/user-guide.md and docs/faq.md.
- Enhanced docs/troubleshooting.md with AI/Agentic issues.
- Updated README.md with CLI Quick Start and Help links.
- Restored original mkdocs.yml navigation and added new user documentation sections.
- Fixed formatting in pkg/io/local/client.go to ensure CI passes.

* docs: add user documentation and fix auto-merge workflow

- Created docs/user-guide.md and docs/faq.md with user-focused content.
- Enhanced docs/troubleshooting.md with AI/Agentic issue solutions.
- Updated README.md with CLI Quick Start and organized help links.
- Refactored mkdocs.yml to include new documentation while preserving technical sections.
- Fixed .github/workflows/auto-merge.yml by inlining the logic and adding git repository context (checkout and -R flag) to resolve CI failures.
- Verified that docs/workflows.md is present in the repository.

* docs: add user documentation and resolve merge conflict

- Created docs/user-guide.md and docs/faq.md.
- Enhanced docs/troubleshooting.md with AI/Agentic issue solutions.
- Updated README.md with CLI Quick Start and Help sections.
- Merged latest base branch changes and resolved conflict in .github/workflows/auto-merge.yml.
- Verified and organized mkdocs.yml navigation.

* docs: add user documentation and fix UniFi security issue

- Created docs/user-guide.md and docs/faq.md.
- Enhanced docs/troubleshooting.md.
- Updated README.md with CLI Quick Start.
- Fixed UniFi security vulnerability (CodeQL alert) by making TLS verification configurable.
- Added --insecure flag to UniFi CLI commands.
- Verified all documentation links and navigation.

* docs: add user documentation and fix formatting/security

- Created docs/user-guide.md and docs/faq.md.
- Enhanced docs/troubleshooting.md.
- Updated README.md with CLI Quick Start.
- Fixed UniFi security vulnerability by making TLS verification configurable.
- Added --insecure flag to UniFi CLI commands.
- Fixed formatting in internal/cmd/unifi/cmd_config.go.
- Verified all documentation links and navigation.

---------

Co-authored-by: Claude <developers@lethean.io>
This commit is contained in:
Snider 2026-02-05 06:55:52 +00:00 committed by GitHub
parent 2b32633b7c
commit d83de64728
13 changed files with 351 additions and 30 deletions

View file

@ -22,7 +22,26 @@ Core is an **opinionated Web3 desktop application framework** providing:
**Mental model:** A secure, encrypted workspace manager where each "workspace" is a cryptographically isolated environment. The framework handles windows, menus, trays, config, and i18n. **Mental model:** A secure, encrypted workspace manager where each "workspace" is a cryptographically isolated environment. The framework handles windows, menus, trays, config, and i18n.
## Quick Start ## CLI Quick Start
```bash
# 1. Install Core
go install github.com/host-uk/core/cmd/core@latest
# 2. Verify environment
core doctor
# 3. Run tests in any Go/PHP project
core go test # or core php test
# 4. Build and preview release
core build
core ci
```
For more details, see the [User Guide](docs/user-guide.md).
## Framework Quick Start (Go)
```go ```go
import core "github.com/host-uk/core" import core "github.com/host-uk/core"
@ -344,6 +363,24 @@ Implementations: `local/`, `sftp/`, `webdav/`
--- ---
## Getting Help
- **[User Guide](docs/user-guide.md)**: Detailed usage and concepts.
- **[FAQ](docs/faq.md)**: Frequently asked questions.
- **[Workflows](docs/workflows.md)**: Common task sequences.
- **[Troubleshooting](docs/troubleshooting.md)**: Solving common issues.
- **[Configuration](docs/configuration.md)**: Config file reference.
```bash
# Check environment
core doctor
# Command help
core <command> --help
```
---
## For New Contributors ## For New Contributors
1. Run `task test` to verify all tests pass 1. Run `task test` to verify all tests pass

97
docs/faq.md Normal file
View file

@ -0,0 +1,97 @@
# Frequently Asked Questions (FAQ)
Common questions and answers about the Core CLI and Framework.
## General
### What is Core?
Core is a unified CLI and framework for building and managing Go, PHP, and Wails applications. It provides an opinionated set of tools for development, testing, building, and releasing projects within the host-uk ecosystem.
### Is Core a CLI or a Framework?
It is both. The Core Framework (`pkg/core`) is a library for building Go desktop applications with Wails. The Core CLI (`cmd/core`) is the tool you use to manage projects, run tests, build binaries, and handle multi-repository workspaces.
---
## Installation
### How do I install the Core CLI?
The recommended way is via Go:
```bash
go install github.com/host-uk/core/cmd/core@latest
```
Ensure your Go bin directory is in your PATH. See [Getting Started](getting-started.md) for more options.
### I get "command not found: core" after installation.
This usually means your Go bin directory is not in your system's PATH. Add it by adding this to your shell profile (`.bashrc`, `.zshrc`, etc.):
```bash
export PATH="$PATH:$(go env GOPATH)/bin"
```
---
## Usage
### Why does `core ci` not publish anything by default?
Core is designed to be **safe by default**. `core ci` runs in dry-run mode to show you what would be published. To actually publish a release, you must use the `--we-are-go-for-launch` flag:
```bash
core ci --we-are-go-for-launch
```
### How do I run tests for only one package?
You can pass standard Go test flags to `core go test`:
```bash
core go test ./pkg/my-package
```
### What is `core doctor` for?
`core doctor` checks your development environment to ensure all required tools (Go, Git, Docker, etc.) are installed and correctly configured. It's the first thing you should run if something isn't working.
---
## Configuration
### Where is Core's configuration stored?
- **Project-specific**: In the `.core/` directory within your project root.
- **Global**: In `~/.core/` or as defined by `CORE_CONFIG`.
- **Registry**: The `repos.yaml` file defines the multi-repo workspace.
### How do I change the build targets?
You can specify targets in `.core/release.yaml` or use the `--targets` flag with the `core build` command:
```bash
core build --targets linux/amd64,darwin/arm64
```
---
## Workspaces and Registry
### What is a "workspace" in Core?
In the context of the CLI, a workspace is a directory containing multiple repositories defined in a `repos.yaml` file. The `core dev` commands allow you to manage status, commits, and synchronization across all repositories in the workspace at once.
### What is `repos.yaml`?
`repos.yaml` is the "registry" for your workspace. It lists the repositories, their types (foundation, module, product), and their dependencies. Core uses this file to know which repositories to clone during `core setup`.
---
## See Also
- [Getting Started](getting-started.md) - Installation and first steps
- [User Guide](user-guide.md) - Detailed usage information
- [Troubleshooting](troubleshooting.md) - Solving common issues

View file

@ -293,6 +293,30 @@ go mod download
--- ---
## AI and Agentic Issues
### "ANTHROPIC_API_KEY not set"
**Cause:** You're trying to use `core ai` or `core dev commit` (which uses Claude for messages) without an API key.
**Fix:**
```bash
export ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxx
```
### "failed to connect to Agentic API"
**Cause:** Network issues or incorrect `AGENTIC_BASE_URL`.
**Fix:**
1. Check your internet connection
2. If using a custom endpoint, verify `AGENTIC_BASE_URL`
3. Ensure you are authenticated if required: `export AGENTIC_TOKEN=xxxx`
---
## Getting More Help ## Getting More Help
### Enable Verbose Output ### Enable Verbose Output

100
docs/user-guide.md Normal file
View file

@ -0,0 +1,100 @@
# User Guide
This guide provides a comprehensive overview of how to use the Core CLI to manage your development workflow.
## Key Concepts
### Projects
A Project is a single repository containing code (Go, PHP, or Wails). Core helps you test, build, and release these projects using a consistent set of commands.
### Workspaces
A Workspace is a collection of related projects. Core is designed to work across multiple repositories, allowing you to perform actions (like checking status or committing changes) on all of them at once.
### Registry (`repos.yaml`)
The Registry is a configuration file that defines the repositories in your workspace. It includes information about where they are located on GitHub, their dependencies, and their purpose.
---
## Daily Workflow
### Working with a Single Project
For a typical day-to-day development on a single project:
1. **Verify your environment**:
```bash
core doctor
```
2. **Run tests while you work**:
```bash
core go test
```
3. **Keep code clean**:
```bash
core go fmt --fix
core go lint
```
4. **Build and preview**:
```bash
core build
```
### Working with Multiple Repositories
If you are working across many repositories in a workspace:
1. **Check status of all repos**:
```bash
core dev work --status
```
2. **Sync all changes**:
```bash
core dev pull --all
```
3. **Commit and push everything**:
```bash
core dev work
```
---
## Building and Releasing
Core separates the building of artifacts from the releasing of those artifacts.
### 1. Build
The `core build` command detects your project type and builds binaries for your configured targets. Artifacts are placed in the `dist/` directory.
### 2. Preview Release
Use `core ci` to see a summary of what would be included in a release (changelog, artifacts, etc.). This is a dry-run by default.
### 3. Publish Release
When you are ready to publish to GitHub:
```bash
core ci --we-are-go-for-launch
```
---
## PHP and Laravel Development
Core provides a unified development server for Laravel projects that orchestrates several services:
```bash
core php dev
```
This starts FrankenPHP, Vite, Horizon, Reverb, and Redis as configured in your `.core/php.yaml`.
---
## Common Workflows
For detailed examples of common end-to-end workflows, see the [Workflows](workflows.md) page.
---
## Getting More Help
- Use the `--help` flag with any command: `core build --help`
- Check the [FAQ](faq.md) for common questions.
- If you run into trouble, see the [Troubleshooting Guide](troubleshooting.md).

View file

@ -39,7 +39,7 @@ func runClients() error {
return log.E("unifi.clients", "conflicting flags", errors.New("--wired and --wireless cannot both be set")) return log.E("unifi.clients", "conflicting flags", errors.New("--wired and --wireless cannot both be set"))
} }
client, err := uf.NewFromConfig("", "", "", "") client, err := uf.NewFromConfig("", "", "", "", nil)
if err != nil { if err != nil {
return log.E("unifi.clients", "failed to initialise client", err) return log.E("unifi.clients", "failed to initialise client", err)
} }

View file

@ -9,11 +9,12 @@ import (
// Config command flags. // Config command flags.
var ( var (
configURL string configURL string
configUser string configUser string
configPass string configPass string
configAPIKey string configAPIKey string
configTest bool configInsecure bool
configTest bool
) )
// addConfigCommand adds the 'config' subcommand for UniFi connection setup. // addConfigCommand adds the 'config' subcommand for UniFi connection setup.
@ -23,7 +24,7 @@ func addConfigCommand(parent *cli.Command) {
Short: "Configure UniFi connection", Short: "Configure UniFi connection",
Long: "Set the UniFi controller URL and credentials, or test the current connection.", Long: "Set the UniFi controller URL and credentials, or test the current connection.",
RunE: func(cmd *cli.Command, args []string) error { RunE: func(cmd *cli.Command, args []string) error {
return runConfig() return runConfig(cmd)
}, },
} }
@ -31,15 +32,21 @@ func addConfigCommand(parent *cli.Command) {
cmd.Flags().StringVar(&configUser, "user", "", "UniFi username") cmd.Flags().StringVar(&configUser, "user", "", "UniFi username")
cmd.Flags().StringVar(&configPass, "pass", "", "UniFi password") cmd.Flags().StringVar(&configPass, "pass", "", "UniFi password")
cmd.Flags().StringVar(&configAPIKey, "apikey", "", "UniFi API key") cmd.Flags().StringVar(&configAPIKey, "apikey", "", "UniFi API key")
cmd.Flags().BoolVar(&configInsecure, "insecure", false, "Allow insecure TLS connections (e.g. self-signed certs)")
cmd.Flags().BoolVar(&configTest, "test", false, "Test the current connection") cmd.Flags().BoolVar(&configTest, "test", false, "Test the current connection")
parent.AddCommand(cmd) parent.AddCommand(cmd)
} }
func runConfig() error { func runConfig(cmd *cli.Command) error {
var insecure *bool
if cmd.Flags().Changed("insecure") {
insecure = &configInsecure
}
// If setting values, save them first // If setting values, save them first
if configURL != "" || configUser != "" || configPass != "" || configAPIKey != "" { if configURL != "" || configUser != "" || configPass != "" || configAPIKey != "" || insecure != nil {
if err := uf.SaveConfig(configURL, configUser, configPass, configAPIKey); err != nil { if err := uf.SaveConfig(configURL, configUser, configPass, configAPIKey, insecure); err != nil {
return err return err
} }
@ -55,11 +62,14 @@ func runConfig() error {
if configAPIKey != "" { if configAPIKey != "" {
cli.Success("UniFi API key saved") cli.Success("UniFi API key saved")
} }
if insecure != nil {
cli.Success(fmt.Sprintf("UniFi insecure mode set to %v", *insecure))
}
} }
// If testing, verify the connection // If testing, verify the connection
if configTest { if configTest {
return runConfigTest() return runConfigTest(cmd)
} }
// If no flags, show current config // If no flags, show current config
@ -71,7 +81,7 @@ func runConfig() error {
} }
func showConfig() error { func showConfig() error {
url, user, pass, apikey, err := uf.ResolveConfig("", "", "", "") url, user, pass, apikey, insecure, err := uf.ResolveConfig("", "", "", "", nil)
if err != nil { if err != nil {
return err return err
} }
@ -101,13 +111,20 @@ func showConfig() error {
cli.Print(" %s %s\n", dimStyle.Render("API Key:"), warningStyle.Render("not set")) cli.Print(" %s %s\n", dimStyle.Render("API Key:"), warningStyle.Render("not set"))
} }
cli.Print(" %s %s\n", dimStyle.Render("Insecure:"), valueStyle.Render(fmt.Sprintf("%v", insecure)))
cli.Blank() cli.Blank()
return nil return nil
} }
func runConfigTest() error { func runConfigTest(cmd *cli.Command) error {
client, err := uf.NewFromConfig(configURL, configUser, configPass, configAPIKey) var insecure *bool
if cmd.Flags().Changed("insecure") {
insecure = &configInsecure
}
client, err := uf.NewFromConfig(configURL, configUser, configPass, configAPIKey, insecure)
if err != nil { if err != nil {
return err return err
} }

View file

@ -32,7 +32,7 @@ func addDevicesCommand(parent *cli.Command) {
} }
func runDevices() error { func runDevices() error {
client, err := uf.NewFromConfig("", "", "", "") client, err := uf.NewFromConfig("", "", "", "", nil)
if err != nil { if err != nil {
return log.E("unifi.devices", "failed to initialise client", err) return log.E("unifi.devices", "failed to initialise client", err)
} }

View file

@ -30,7 +30,7 @@ func addNetworksCommand(parent *cli.Command) {
} }
func runNetworks() error { func runNetworks() error {
client, err := uf.NewFromConfig("", "", "", "") client, err := uf.NewFromConfig("", "", "", "", nil)
if err != nil { if err != nil {
return log.E("unifi.networks", "failed to initialise client", err) return log.E("unifi.networks", "failed to initialise client", err)
} }

View file

@ -32,7 +32,7 @@ func addRoutesCommand(parent *cli.Command) {
} }
func runRoutes() error { func runRoutes() error {
client, err := uf.NewFromConfig("", "", "", "") client, err := uf.NewFromConfig("", "", "", "", nil)
if err != nil { if err != nil {
return log.E("unifi.routes", "failed to initialise client", err) return log.E("unifi.routes", "failed to initialise client", err)
} }

View file

@ -21,7 +21,7 @@ func addSitesCommand(parent *cli.Command) {
} }
func runSites() error { func runSites() error {
client, err := uf.NewFromConfig("", "", "", "") client, err := uf.NewFromConfig("", "", "", "", nil)
if err != nil { if err != nil {
return log.E("unifi.sites", "failed to initialise client", err) return log.E("unifi.sites", "failed to initialise client", err)
} }

View file

@ -43,6 +43,26 @@ markdown_extensions:
nav: nav:
- Home: index.md - Home: index.md
- User Documentation:
- User Guide: user-guide.md
- FAQ: faq.md
- Troubleshooting: troubleshooting.md
- Workflows: workflows.md
- CLI Reference:
- Overview: cmd/index.md
- AI: cmd/ai/index.md
- Build: cmd/build/index.md
- CI: cmd/ci/index.md
- Dev: cmd/dev/index.md
- Go: cmd/go/index.md
- PHP: cmd/php/index.md
- SDK: cmd/sdk/index.md
- Setup: cmd/setup/index.md
- Doctor: cmd/doctor/index.md
- Test: cmd/test/index.md
- VM: cmd/vm/index.md
- Pkg: cmd/pkg/index.md
- Docs: cmd/docs/index.md
- Getting Started: - Getting Started:
- Installation: getting-started/installation.md - Installation: getting-started/installation.md
- Quick Start: getting-started/quickstart.md - Quick Start: getting-started/quickstart.md
@ -77,3 +97,14 @@ nav:
- API Reference: - API Reference:
- Core: api/core.md - Core: api/core.md
- Display: api/display.md - Display: api/display.md
- Development:
- Package Standards: pkg/PACKAGE_STANDARDS.md
- Internationalization:
- Overview: pkg/i18n/README.md
- Grammar: pkg/i18n/GRAMMAR.md
- Extending: pkg/i18n/EXTENDING.md
- Claude Skill: skill/index.md
- Reference:
- Configuration: configuration.md
- Migration: migration.md
- Glossary: glossary.md

View file

@ -16,8 +16,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 is disabled by default (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).
func New(url, user, pass, apikey string) (*Client, error) { func New(url, user, pass, apikey string, insecure bool) (*Client, error) {
cfg := &uf.Config{ cfg := &uf.Config{
URL: url, URL: url,
User: user, User: user,
@ -25,11 +25,11 @@ func New(url, user, pass, apikey string) (*Client, error) {
APIKey: apikey, APIKey: apikey,
} }
// Skip TLS verification for self-signed certs // Skip TLS verification if requested (e.g. for self-signed certs)
httpClient := &http.Client{ httpClient := &http.Client{
Transport: &http.Transport{ Transport: &http.Transport{
TLSClientConfig: &tls.Config{ TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, //nolint:gosec InsecureSkipVerify: insecure,
MinVersion: tls.VersionTLS12, MinVersion: tls.VersionTLS12,
}, },
}, },

View file

@ -24,6 +24,8 @@ const (
ConfigKeyPass = "unifi.pass" ConfigKeyPass = "unifi.pass"
// ConfigKeyAPIKey is the config key for the UniFi API key. // ConfigKeyAPIKey is the config key for the UniFi API key.
ConfigKeyAPIKey = "unifi.apikey" ConfigKeyAPIKey = "unifi.apikey"
// ConfigKeyInsecure is the config key for allowing insecure TLS connections.
ConfigKeyInsecure = "unifi.insecure"
// DefaultURL is the default UniFi controller URL. // DefaultURL is the default UniFi controller URL.
DefaultURL = "https://10.69.1.1" DefaultURL = "https://10.69.1.1"
@ -32,10 +34,10 @@ const (
// NewFromConfig creates a UniFi client using the standard config resolution: // NewFromConfig creates a UniFi client using the standard config resolution:
// //
// 1. ~/.core/config.yaml keys: unifi.url, unifi.user, unifi.pass, unifi.apikey // 1. ~/.core/config.yaml keys: unifi.url, unifi.user, unifi.pass, unifi.apikey
// 2. UNIFI_URL + UNIFI_USER + UNIFI_PASS + UNIFI_APIKEY environment variables (override config file) // 2. UNIFI_URL + UNIFI_USER + UNIFI_PASS + UNIFI_APIKEY + UNIFI_INSECURE environment variables (override config file)
// 3. Provided flag overrides (highest priority; pass empty to skip) // 3. Provided flag overrides (highest priority; pass empty to skip)
func NewFromConfig(flagURL, flagUser, flagPass, flagAPIKey string) (*Client, error) { func NewFromConfig(flagURL, flagUser, flagPass, flagAPIKey string, flagInsecure *bool) (*Client, error) {
url, user, pass, apikey, err := ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey) url, user, pass, apikey, insecure, err := ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey, flagInsecure)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -44,12 +46,12 @@ func NewFromConfig(flagURL, flagUser, flagPass, flagAPIKey string) (*Client, err
return nil, log.E("unifi.NewFromConfig", "no credentials configured (set UNIFI_USER/UNIFI_PASS or UNIFI_APIKEY, or run: core unifi config)", nil) return nil, log.E("unifi.NewFromConfig", "no credentials configured (set UNIFI_USER/UNIFI_PASS or UNIFI_APIKEY, or run: core unifi config)", nil)
} }
return New(url, user, pass, apikey) return New(url, user, pass, apikey, insecure)
} }
// ResolveConfig resolves the UniFi URL and credentials from all config sources. // ResolveConfig resolves the UniFi URL and credentials from all config sources.
// Flag values take highest priority, then env vars, then config file. // Flag values take highest priority, then env vars, then config file.
func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, pass, apikey string, err error) { func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string, flagInsecure *bool) (url, user, pass, apikey string, insecure bool, err error) {
// Start with config file values // Start with config file values
cfg, cfgErr := config.New() cfg, cfgErr := config.New()
if cfgErr == nil { if cfgErr == nil {
@ -57,6 +59,7 @@ func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, p
_ = cfg.Get(ConfigKeyUser, &user) _ = cfg.Get(ConfigKeyUser, &user)
_ = cfg.Get(ConfigKeyPass, &pass) _ = cfg.Get(ConfigKeyPass, &pass)
_ = cfg.Get(ConfigKeyAPIKey, &apikey) _ = cfg.Get(ConfigKeyAPIKey, &apikey)
_ = cfg.Get(ConfigKeyInsecure, &insecure)
} }
// Overlay environment variables // Overlay environment variables
@ -72,6 +75,9 @@ func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, p
if envAPIKey := os.Getenv("UNIFI_APIKEY"); envAPIKey != "" { if envAPIKey := os.Getenv("UNIFI_APIKEY"); envAPIKey != "" {
apikey = envAPIKey apikey = envAPIKey
} }
if envInsecure := os.Getenv("UNIFI_INSECURE"); envInsecure != "" {
insecure = envInsecure == "true" || envInsecure == "1"
}
// Overlay flag values (highest priority) // Overlay flag values (highest priority)
if flagURL != "" { if flagURL != "" {
@ -86,17 +92,20 @@ func ResolveConfig(flagURL, flagUser, flagPass, flagAPIKey string) (url, user, p
if flagAPIKey != "" { if flagAPIKey != "" {
apikey = flagAPIKey apikey = flagAPIKey
} }
if flagInsecure != nil {
insecure = *flagInsecure
}
// Default URL if nothing configured // Default URL if nothing configured
if url == "" { if url == "" {
url = DefaultURL url = DefaultURL
} }
return url, user, pass, apikey, nil return url, user, pass, apikey, insecure, nil
} }
// SaveConfig persists the UniFi URL and/or credentials to the config file. // SaveConfig persists the UniFi URL and/or credentials to the config file.
func SaveConfig(url, user, pass, apikey string) error { func SaveConfig(url, user, pass, apikey string, insecure *bool) error {
cfg, err := config.New() cfg, err := config.New()
if err != nil { if err != nil {
return log.E("unifi.SaveConfig", "failed to load config", err) return log.E("unifi.SaveConfig", "failed to load config", err)
@ -126,5 +135,11 @@ func SaveConfig(url, user, pass, apikey string) error {
} }
} }
if insecure != nil {
if err := cfg.Set(ConfigKeyInsecure, *insecure); err != nil {
return log.E("unifi.SaveConfig", "failed to save insecure flag", err)
}
}
return nil return nil
} }