Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
2705ca5
feat: extract config package from core/go pkg/config
Snider Mar 6, 2026
2a9fe86
refactor: swap pkg/framework imports to pkg/core
Snider Mar 6, 2026
1dced31
chore: sync go.mod dependencies
Snider Mar 6, 2026
c81bf25
chore: add .core/ build and release configs
Snider Mar 6, 2026
ddf301f
fix: add Commit() for safe config writes, iterator-based All()
Snider Mar 9, 2026
67bffa5
docs: add human-friendly documentation
Snider Mar 11, 2026
ea942fb
docs: add CLAUDE.md project instructions
Snider Mar 13, 2026
a3a93b5
fix: update stale import paths and dependency versions from extraction
Snider Mar 14, 2026
b48e795
chore: add .core/ and .idea/ to .gitignore
Snider Mar 15, 2026
62c57e6
fix(config): update CLAUDE.md commands and remove redundant fmt.Sprin…
Snider Mar 17, 2026
9a12aa8
Merge pull request '[agent/claude:sonnet] Fix these issues: 1) Update…
Mar 17, 2026
59b968b
feat: upgrade to core v0.8.0-alpha.1, replace banned stdlib imports
Mar 26, 2026
16a112b
Merge branch 'main' into dev
Snider Apr 3, 2026
f4c2353
Merge pull request #2 from dAppCore/dev
Snider Apr 3, 2026
02b8705
fix: migrate module paths from forge.lthn.ai to dappco.re
Snider Apr 4, 2026
96a5b7a
fix: tidy deps after dappco.re migration
Snider Apr 4, 2026
7df6fe9
fix: update go.sum for dappco.re dependency migration
Snider Apr 7, 2026
ade6874
Merge remote-tracking branch 'github/main'
Snider Apr 7, 2026
db7a67a
fix: migrate module path from forge.lthn.ai to dappco.re
Snider Apr 7, 2026
5a62b9e
fix: add missing fmt import
Snider Apr 7, 2026
3199aed
fix: fully migrate source imports from forge.lthn.ai to dappco.re
Snider Apr 7, 2026
c19a60f
fix(config): update go-io dep for MockMedium support
Snider Apr 8, 2026
02fc381
refactor: AX compliance sweep — replace banned stdlib imports with co…
Snider Apr 13, 2026
64b54bd
feat(config): conclave + discover + feature + schema + watch + xdg
Snider Apr 14, 2026
216dd56
Merge origin/main into main — preserve dev work, take upgraded API
Snider Apr 14, 2026
653cb60
feat(config): implement RFC features — Discover, XDG, manifests, watc…
Snider Apr 14, 2026
c3358aa
feat(config): close spec gaps — known files, manifest types, feature …
Snider Apr 14, 2026
fef30a7
fix(config): match core.WithService signature in NewConfigService
Snider Apr 14, 2026
0031019
feat(config): All() iter with env overrides + ide/php constants
Snider Apr 14, 2026
8df1ce7
fix(config): honour env overrides and prevent inherited-secret leak
Snider Apr 14, 2026
926cd8c
feat(config): add defaults layer + ReposManifest schema
Snider Apr 14, 2026
d826be1
fix(config): AX sweep + watcher rename-survival + conclave isolation …
Snider Apr 14, 2026
39f1484
fix(config): AX convention sweep — gofmt, test naming, AttachCore cov…
Snider Apr 14, 2026
75c3524
feat(config): align manifest schemas with RFC
Snider Apr 15, 2026
eb31d7e
feat(config): mini/code pass 1
Snider Apr 15, 2026
1903100
Support RFC build manifest schema
Snider Apr 15, 2026
81de0dd
feat(config): broadcast file load changes
Snider Apr 15, 2026
95a6d1a
Implement config spec gaps
Snider Apr 15, 2026
c1beb7d
Wire config service registry commands
Snider Apr 15, 2026
4b2637a
Fix discovery config precedence
Snider Apr 15, 2026
df7856c
fix(config): publish loaded features from service
Snider Apr 15, 2026
0961a77
Add schema validation and RFC manifests
Snider Apr 15, 2026
08ef79d
feat(config): align loader with RFC
Snider Apr 15, 2026
57935be
Harden config manifest loading
Snider Apr 15, 2026
be45d1f
feat(config): add workspace manifest resolver
Snider Apr 15, 2026
5ebb1de
Add missing config coverage
Snider Apr 15, 2026
f3ad6a9
Add project manifest resolvers
Snider Apr 15, 2026
b115238
security(config): persist config privately
Snider Apr 15, 2026
8615317
Add missing config manifest tests
Snider Apr 15, 2026
bea90dd
Add php manifest support and explicit store wiring
Snider Apr 15, 2026
866ea9d
Harden config access, manifests, and load path checks
Snider Apr 15, 2026
01ae6e3
scan(config): spark/tester pass 3
Snider Apr 15, 2026
9ed5878
Fix config service and manifest loading
Snider Apr 15, 2026
f6b5cf2
feat(config): add user manifest resolvers
Snider Apr 15, 2026
c3d8d05
Add .core registry path helpers
Snider Apr 15, 2026
59fa093
Add images manifest registry support
Snider Apr 15, 2026
f35a5c5
Align repos manifest resolution with RFC
Snider Apr 15, 2026
0ddde48
Add core directory helpers
Snider Apr 15, 2026
afac0ff
Add named workspace sandbox helpers
Snider Apr 15, 2026
caa4e74
feat(config): align repos and service load paths
Snider Apr 15, 2026
4fd8786
Add default config file version
Snider Apr 15, 2026
3d0404b
Harden config service read access
Snider Apr 15, 2026
f3f35e4
Tighten config service path validation
Snider Apr 15, 2026
2bbdbd9
Add missing config coverage
Snider Apr 15, 2026
33b5167
config: enforce trusted package manifest keys
Snider Apr 15, 2026
ea0d90e
Harden config iterator snapshotting
Snider Apr 15, 2026
71a3d38
Add missing config coverage
Snider Apr 15, 2026
b49c8b4
feat(config): add ide manifest resolution
Snider Apr 15, 2026
b57dfe3
feat(config): always version saved yaml
Snider Apr 15, 2026
3668e4b
feat(config): expose linuxkit manifest path
Snider Apr 15, 2026
490c3bd
fix(config): normalise discovery start paths
Snider Apr 15, 2026
a423b73
Fix config commit broadcast locking
Snider Apr 15, 2026
2a8d587
Add workspace registry manifest aliases
Snider Apr 15, 2026
56d657d
Fix LinuxKit manifest discovery
Snider Apr 15, 2026
b613020
Normalize test command detection start path
Snider Apr 15, 2026
3a6f1eb
Add manifest signing helpers and LinuxKit resolver
Snider Apr 15, 2026
3e15d2e
Harden config path handling
Snider Apr 15, 2026
0503fdd
Reject symlinked core directories
Snider Apr 15, 2026
b3cb323
Add spec-driven config tests
Snider Apr 15, 2026
264f7f2
Fix package manifest trust-root verification
Snider Apr 15, 2026
bff2fd1
security(config): harden conclave and trust-key paths
Snider Apr 15, 2026
62f39fc
Add missing config coverage
Snider Apr 15, 2026
ddba242
config: reload config state from store
Snider Apr 15, 2026
6adadbf
feat(ax-10): bring config to v0.8.0-alpha.1 + CLI test scaffold
Snider Apr 24, 2026
e8feaa5
Merge remote-tracking branch 'github/dev' into dev
Snider Apr 27, 2026
cd4f145
Merge remote-tracking branch 'github/main' into dev
Snider Apr 27, 2026
06abfba
fix(config): address all CodeRabbit + SonarCloud findings on PR #3
Snider Apr 27, 2026
595572c
ci: woodpecker pipeline (Go) — golangci-lint/eslint/phpstan + sonar.l…
Snider Apr 28, 2026
e7086af
refactor(core): full v0.9.0 compliance against core/go reference
Snider Apr 28, 2026
3c689bb
merge: codex/v0.9.0-config
Snider Apr 28, 2026
53111ee
ci: woodpecker pipeline (Go) — golangci-lint/eslint/phpstan + sonar.l…
Snider Apr 28, 2026
c852d98
refactor(core): align config with hardened core/go reference shape
Snider Apr 29, 2026
9320e07
refactor(core): config round 2 — full 24-dim COMPLIANT
Snider Apr 29, 2026
eb087c0
chore(deps): bump dappco.re/go/* deps to v0.9.0, drop sibling replaces
Snider Apr 30, 2026
905216d
chore(deps): tidy after dappco.re vanity migration
Snider Apr 30, 2026
aba665e
chore(config): restructure Go module under go/ + go.work + external/ …
Snider Apr 30, 2026
00fc49f
chore(lint): clear golangci-lint findings (errcheck/staticcheck)
Snider Apr 30, 2026
34e2fb8
ci(public): add github actions workflow + README badge block
Snider Apr 30, 2026
0b4c944
docs: import core-folder-spec.md from agent
Snider Apr 30, 2026
5224614
chore(sonar): address all 85 code smells (5.4-mini lane)
Snider Apr 30, 2026
b4b3b56
merge: incorporate main history (dev preserves restructured layout)
Snider Apr 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
80 changes: 80 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: CI

on:
push:
branches: [dev, main]
pull_request:
branches: [dev, main]

permissions:
contents: read

env:
GOFLAGS: -buildvcs=false
GOWORK: "off"
GOPROXY: "direct"
GOSUMDB: "off"

jobs:
test:
name: Test + Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: actions/setup-go@v6
with:
go-version: '1.26'
- name: Test with coverage
working-directory: go
run: go test -race -coverprofile=coverage.out -covermode=atomic -count=1 ./...
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: go/coverage.out
flags: unittests
fail_ci_if_error: false

lint:
name: golangci-lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-go@v6
with:
go-version: '1.26'
- uses: golangci/golangci-lint-action@v9
with:
version: latest
working-directory: go
args: --timeout=5m --tests=false

sonarcloud:
name: SonarCloud
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: actions/setup-go@v6
with:
go-version: '1.26'
- name: Test for coverage
working-directory: go
run: go test -coverprofile=coverage.out -covermode=atomic -count=1 ./...
- name: SonarCloud Scan
uses: SonarSource/sonarqube-scan-action@v6
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
args: >
-Dsonar.organization=dappcore
-Dsonar.projectKey=dappcore_config
-Dsonar.sources=go
-Dsonar.exclusions=**/vendor/**,**/third_party/**,**/.tmp/**,**/*_test.go
-Dsonar.tests=go
-Dsonar.test.inclusions=**/*_test.go
-Dsonar.go.coverage.reportPaths=go/coverage.out
12 changes: 12 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[submodule "external/go"]
path = external/go
url = https://github.com/dappcore/go.git
branch = dev
[submodule "external/io"]
path = external/io
url = https://github.com/dappcore/go-io.git
branch = dev
[submodule "external/log"]
path = external/log
url = https://github.com/dappcore/go-log.git
branch = dev
4 changes: 2 additions & 2 deletions .woodpecker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ steps:
GOFLAGS: -buildvcs=false
GOWORK: "off"
commands:
- golangci-lint run --timeout=5m ./...
- cd go && golangci-lint run --timeout=5m ./...

- name: go-test
image: golang:1.26-alpine
Expand All @@ -25,7 +25,7 @@ steps:
CGO_ENABLED: "1"
commands:
- apk add --no-cache git build-base
- go test -race -coverprofile=coverage.out -covermode=atomic -count=1 ./...
- cd go && go test -race -coverprofile=coverage.out -covermode=atomic -count=1 ./...
- name: sonar
image: sonarsource/sonar-scanner-cli:latest
depends_on: [go-test]
Expand Down
63 changes: 23 additions & 40 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,32 @@
# Agent Guide
# Agent Notes

This repository is the `dappco.re/go/config` consumer module for Core
configuration. Work here should follow the current `dappco.re/go` conventions:
public operations return `core.Result`, tests use the Core assertion helpers,
and examples print through `core.Println`.
This repository is the `dappco.re/go/config` module. It provides layered
configuration, manifest loading, discovery, feature flags, XDG paths, and the
Core framework service adapter used by other Core projects.

## Repository Shape
When changing code here, keep the public API aligned with `dappco.re/go` v0.9
patterns. Use the Core wrappers for formatting, JSON, filesystem paths,
environment reads, and assertions in tests. Do not add direct imports of the
stdlib packages banned by the upgrade audit, and do not create compatibility
packages that shadow those stdlib names.

- `config.go` contains the `Config` type, functional options, file loading,
typed retrieval, persistence, and legacy `Load` / `Save` helpers.
- `env.go` contains environment scanning helpers. It maps prefixed variables to
lower-case dot keys without importing banned stdlib packages directly.
- `service.go` wraps `Config` as a Core lifecycle service.
- Each production file has a matching `_test.go` and `_example_test.go` sibling.
Keep tests next to their source file; do not create aggregate compliance
files.
- `docs/` contains the human-facing architecture and development notes.
Tests are source-file aware. Public symbols in `config.go` are tested in
`config_test.go`, public symbols in `resolve.go` are tested in
`resolve_test.go`, and so on. Each public symbol needs the Good, Bad, and Ugly
triplet in that sibling file plus a runnable example in the matching
`*_example_test.go` file. Supplemental tests may exist, but their names should
describe the behaviour they cover rather than pretending to be another
symbol's canonical triplet.

## Compliance Rules

The audit script is the work provider:
The normal verification gate for this repository is:

```bash
GOWORK=off go mod tidy
GOWORK=off go vet ./...
GOWORK=off go test -count=1 ./...
gofmt -l .
bash /Users/snider/Code/core/go/tests/cli/v090-upgrade/audit.sh .
```

Do not stop on partial progress. A compliant run has every counter at `0` and
prints `verdict: COMPLIANT`.

The important local patterns are:

- Use `core.Result` with `core.Ok`, `core.Fail`, or `core.ResultOf`.
- Do not import banned stdlib packages such as `fmt`, `os`, `strings`,
`path/filepath`, or `encoding/json` in this consumer module.
- Use `core.Path*`, `core.Environ`, `core.SplitN`, `core.Replace`, and
`core.Sprintf` instead of direct stdlib helpers.
- Public symbols require `Good`, `Bad`, and `Ugly` tests in the matching source
test file.
- Public symbols require examples in the matching source example file.

## Editing Notes

Keep the dual-view config invariant intact. File-backed and explicitly set
values belong in `Config.file`; the read view in `Config.full` is rebuilt from
file settings, environment variables, and explicit overrides. That separation is
what prevents environment-derived secrets from being written during `Commit`.

Do not edit `BRIEF.md`, `.git`, `.codex`, or any `third_party` directory.
`BRIEF.md` is a local work brief and should be left untracked. Do not edit
`third_party/`, `.git/`, or `.codex/` while applying compliance changes.
117 changes: 79 additions & 38 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,100 @@
# CLAUDE.md

This file gives Claude Code agents repository-specific context for
`dappco.re/go/config`.
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Repo Layout

```text
core/config/
├── go/
│ ├── *.go ← Go source files moved from repository root
│ ├── tests/ ← Go CLI tests moved from repository root
│ ├── go.mod
│ ├── go.sum
│ ├── README.md -> ../README.md ← symlink
│ ├── CLAUDE.md -> ../CLAUDE.md ← symlink
│ ├── AGENTS.md -> ../AGENTS.md ← symlink
│ └── docs -> ../docs ← symlink
├── docs/
├── schema/
├── README.md
├── CLAUDE.md
├── AGENTS.md
├── LICENSE/
├── SONAR-project files
└── other non-Go/cross-language assets
```

The Go module path remains `dappco.re/go/config`; only repository layout changed.

## Go Resolution Modes

This repository is module-local under `go/` and does not use a local workspace file in this module root. Consumer commands should either:

## Commands
1. Run from `go/` directly.
2. Prefix Go commands with `cd go &&` when executed from repository root.

Use the explicit verification commands from the compliance brief:
Examples:

```bash
GOWORK=off go mod tidy
GOWORK=off go vet ./...
GOWORK=off go test -count=1 ./...
gofmt -l .
bash /Users/snider/Code/core/go/tests/cli/v090-upgrade/audit.sh .
cd go && go test ./...
cd go && golangci-lint run ./...
cd go && core go qa
```

The audit script is the completion contract. The repository is not complete
until every audit counter is `0` and the verdict is `COMPLIANT`.
For CI-style reproducible builds, force module-only behavior:

## Architecture
```bash
GOWORK=off go test ./...
GOFLAGS=-mod=mod go vet ./...
```

`Config` uses two Viper instances:
## Build & Test Commands

- `file` stores values loaded from config files and values explicitly set at
runtime. This is the only source written by `Commit`.
- `full` is the read view. It is rebuilt from file settings, environment
variables, and explicit overrides.
This project uses the Core CLI (`core` binary), not `go` directly.

This shape keeps environment-derived secrets out of persisted YAML while still
letting `Get` and `All` see the effective runtime configuration.
```bash
cd go && go test ./... # run all tests
cd go && GOWORK=off go test -run TestConfig_Get_Good ./... # run a single test
cd go && GOWORK=off go test -cover ./... # test with coverage

cd go && core go qa # format, vet, lint, test
cd go && core go qa full # adds race detector, vuln scan, security audit

cd go && core go fmt # format
cd go && core go vet # vet
cd go && core go lint # lint
```

This is a library package — there is no binary to build or run.

## Architecture

## API Conventions
**Dual-Viper pattern**: `Config` holds two `*viper.Viper` instances:
- `v` (full) — file + env + defaults; used for all reads (`Get`, `All`)
- `f` (file-only) — file + explicit `Set()` calls; used for persistence (`Commit`)

This consumer repo follows `dappco.re/go` v0.9.0 conventions:
This prevents environment variables from leaking into saved config files. When implementing new features, maintain this invariant: writes go to both `v` and `f`; reads come from `v`; persistence comes from `f`.

- Public operations return `core.Result`.
- Callers branch on `r.OK` and read `r.Value` or `r.Error()`.
- Use `core.Ok`, `core.Fail`, and `core.ResultOf` rather than struct literals.
- Do not import banned stdlib packages directly. Reach through Core wrappers
such as `core.PathExt`, `core.PathDir`, `core.Environ`, `core.SplitN`,
`core.Replace`, `core.NewReader`, and `core.Sprintf`.
**Resolution priority** (ascending): defaults → file → env vars (`CORE_CONFIG_*`) → `Set()`

## Tests And Examples
**Service wrapper**: `Service` in `service.go` wraps `Config` with framework lifecycle (`core.Startable`). Both `Config` and `Service` satisfy `core.Config`, enforced by compile-time assertions.

Each production file with public symbols has a sibling test file and a sibling
example file. Keep coverage file-aware:
**Storage abstraction**: All file I/O goes through `coreio.Medium` (from `go-io`). Tests use `coreio.NewMockMedium()` with an in-memory `Files` map — never touch the real filesystem.

- `config.go` -> `config_test.go` and `config_example_test.go`
- `env.go` -> `env_test.go` and `env_example_test.go`
- `service.go` -> `service_test.go` and `service_example_test.go`
## Conventions

Tests use `*core.T`, dot-import `dappco.re/go`, and the Core assertion helpers.
Triplets are named `Test<File>_<Symbol>_{Good,Bad,Ugly}`. Examples use
`core.Println`, not `fmt.Println`.
- **UK English** in comments and documentation (colour, organisation, centre)
- **Error wrapping**: `coreerr.E(caller, message, underlying)` from `go-log`
- **Test naming**: `_Good` (happy path), `_Bad` (expected errors), `_Ugly` (panics/edge cases)
- **Functional options**: `New()` takes `...Option` (e.g. `WithMedium`, `WithPath`, `WithEnvPrefix`)
- **Conventional commits**: `type(scope): description`
- **Go workspace**: no per-repo `go.work`; this module resolves with `GOWORK=off`

## Do Not Touch
## Dependencies

Do not edit `BRIEF.md`, `.git`, `.codex`, or any `third_party` directory.
- `dappco.re/go/core/io` — `Medium` interface for storage
- `dappco.re/go/core/log` — `coreerr.E()` error helper
- `dappco.re/go/core` — `core.Core`, `core.Startable`, `core.ServiceRuntime`, primitives
- `github.com/spf13/viper` — configuration engine
- `github.com/stretchr/testify` — test assertions
Loading
Loading