ZDDC/zddc/internal/zddc/defaults.go
ZDDC d84c1908f6 feat(zddc): Phase 1 — embedded defaults.zddc + inherit + show-defaults
First step of the .zddc-first-configuration rollout: pure plumbing
that makes the future move-everything-out-of-Go work mechanically
possible without changing any current behaviour.

New pieces:

1. zddc/internal/zddc/defaults.zddc.yaml — a real YAML file in the
   repo. Single source of truth for the baked-in baseline; intentionally
   minimal in Phase 1 (just title + empty acl) so existing deployments
   stay bit-identical until Phase 2 starts populating the schema.

2. //go:embed (defaults.go) bakes the bytes into the binary so
   shipped deployments don't need the file. Operators who want a
   starting point export with:

       zddc-server show-defaults > /var/lib/zddc/root/.zddc

3. PolicyChain gains an Embedded ZddcFile field. EffectivePolicy
   layers in the embedded defaults as a baseline below the on-disk
   chain. Consumers that want the full effective view consult both;
   existing consumers that only read chain.Levels keep working
   bit-identically (the new field is additive).

4. New top-level `inherit:` key on ZddcFile. Default true. Set
   `inherit: false` on any on-disk .zddc to zero out chain.Embedded
   — the operator owns every rule from that level outward. Useful at
   the on-disk root to fully reject the embedded defaults; useful at
   deeper levels for sandbox subtrees.

5. `zddc-server show-defaults` (also accepts --show-defaults) subcommand
   dumps the embedded bytes to stdout — same shape as --print-rego.
   No flag plumbing needed beyond the existing args walk.

6. Tests: parse-roundtrip on the embedded file, presence in chain by
   default, inherit:false drops it, explicit inherit:true is a no-op
   versus the default.

Phase 2 (next): add a `paths:` recursive map + `default_tool:` /
`auto_own:` / `virtual:` keys, populate defaults.zddc.yaml with the
canonical ZDDC convention, and migrate apps.DefaultAppAt /
AutoOwnCanonicalNames / VirtualOnlyCanonicalNames to cascade lookups.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 14:46:51 -05:00

40 lines
1.1 KiB
Go

package zddc
import (
_ "embed"
"sync"
)
// defaultsBytes is the embedded baseline .zddc — see defaults.zddc.yaml
// for the source-of-truth and a description of its role in the cascade.
//
//go:embed defaults.zddc.yaml
var defaultsBytes []byte
// EmbeddedDefaultsBytes returns the raw embedded defaults YAML.
//
// Surface: the show-defaults CLI subcommand dumps these bytes to
// stdout so operators can copy them into <ZDDC_ROOT>/.zddc and edit.
func EmbeddedDefaultsBytes() []byte {
out := make([]byte, len(defaultsBytes))
copy(out, defaultsBytes)
return out
}
var (
embeddedDefaultsOnce sync.Once
embeddedDefaults ZddcFile
embeddedDefaultsErr error
)
// EmbeddedDefaults returns the parsed embedded defaults ZddcFile,
// memoised. Parse errors surface on the first call and are sticky.
//
// The cascade walker (EffectivePolicy) consults this as the bottom-
// most level unless an on-disk .zddc up the chain sets `inherit: false`.
func EmbeddedDefaults() (ZddcFile, error) {
embeddedDefaultsOnce.Do(func() {
embeddedDefaults, embeddedDefaultsErr = parseBytes(defaultsBytes)
})
return embeddedDefaults, embeddedDefaultsErr
}