Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ while in pre-1.0 mode (`v0.x.y`).
### Changed

- **BREAKING (`pkg/nucleus` rewrite — ADR-010 Phase 1 Foundation): the legacy fluent chain is replaced wholesale.** The pre-Phase-1 surface (`nucleus.New().Port().Host().SQLite().Postgres().MySQL().WithAdmin().SPA().Templates().Static().Cors().Provide().Model().AutoMigrate().Run()`, the `Resource(path, controller)` shape requiring a five-method controller, the `RouterGroup` struct, the legacy `Load(path)` that panicked on error) is removed entirely. The new surface — canonical `nucleus.App{}` struct embedding `app.Config`, generic `nucleus.Module[C any]` with `Build() ModuleSpec`, `nucleus.Router` interface with three coexisting registration styles (flat, REST `Resource(path, controller, nucleus.Methods(...))` with explicit verb registration, and nested `Group(prefix, func(g Router))`), three coexisting entry surfaces (fluent builder, direct struct, bootstrap pattern) producing equal `App{}` values per `pkg/nucleus/equivalence_test.go` — lands in this PR. `FromConfigFile` is shape-only in Phase 1 and returns `ErrConfigLoaderNotImplemented` at `Build`/`Start`/`Serve` time; the five-layer validator and merge engine arrive in Phase 2. Pre-`v1.0` clean break per the ADR-006 / ADR-008 precedent — no DEP/MA artefacts, no WARN-wrapped legacy methods. See [ADR-010](docs/adrs/ADR-010-fluent-api-v2-pkg-nucleus.md).
- **BREAKING (`pkg/nucleus.FromConfigFile` is now operational — ADR-010 Phase 2a): the Phase 1 stub is replaced by a real single-file YAML loader.** `AppBuilder.FromConfigFile(path)` now loads the named file via koanf, applies struct defaults from `app.DefaultConfig()`, and returns a populated `nucleus.App` when called through `Build`/`Start`/`Serve`. Three validation guards land alongside: a **1 MiB per-file size cap** (`MaxConfigFileBytes`) enforced before parsing — eliminates anchor-expansion / deep-nesting DoS classes against `gopkg.in/yaml.v3`; **strict-unknown-fields schema validation** against `app.ContractConfigKeyPatterns()` — unknown keys surface as `ErrUnknownConfigKeys` with did-you-mean hints for likely typos (Levenshtein distance ≤3 on the final segment); and **extension-based parser inference** — `.yaml`/`.yml` work today, `.toml`/`.json` produce a targeted `ErrUnsupportedConfigFormat` referencing Phase 2b. Multi-file `FromConfigFile(a.yaml, b.yaml)` fails fast with a Phase 2b reference until the merge engine lands. `ErrConfigLoaderNotImplemented` is removed (clean break — pre-`v1.0` Phase-1 stub now retired). Three new exported sentinels (`ErrConfigFileTooLarge`, `ErrUnsupportedConfigFormat`, `ErrUnknownConfigKeys`) and one constant (`MaxConfigFileBytes`) join the `pkg/nucleus` baseline. New dep: `github.com/knadh/koanf/providers/rawbytes` (zero-go, sibling of the YAML provider already in tree). See [ADR-010](docs/adrs/ADR-010-fluent-api-v2-pkg-nucleus.md) §2.
- **BREAKING (`examples/*` removed): every example application is removed; new reference applications will land in v0.9.X.** Owner decision dated 2026-05-16, recorded in ADR-010: the original Phase 1 plan rewrote the two `examples/ecommerce_dashboard/backend/*` consumers in the same PR. Instead, the entire `examples/*` tree (`admin-quickstart`, `balancer`, `ecommerce_dashboard`, `fleetmanager`, `ministore`, `mvc_api`, `plugins`) was removed, alongside the runnable lab scripts (`scripts/cluster-{start,stop}.sh`, `scripts/dev/run_admin_cluster_lab.{sh,ps1}`) and the example-dependent docs (`docs/ADMIN_CLUSTER_LAB.md`, `docs/reference/PLUGIN_EXAMPLES.md`). The compatibility harness loses its three fixture profiles (`minimal-api`, `admin-heavy`, `plugin-heavy`) for this window and runs a `core-build` placeholder; the fixture profiles return with the new reference applications in v0.9.X (ADR-010 Phase 4). The `Dockerfile` now builds and ships the `nucleus` CLI rather than the previous `examples/mvc_api` server. Migration is empty for external users (there were none); operators downstream that previously consumed the example-server Docker image should pin to a pre-2026-05-16 tag until v0.9.X.
- **Behaviour change (`pkg/observe`, stable surface): `NewLogger` redacts secret-keyed attributes by default.** A deployment that intentionally logged a field under a denylisted key (e.g. an opaque non-secret named `token`) now sees `[REDACTED]` there. This is the intended security default per [ADR-007](docs/adrs/ADR-007-slog-secret-redaction.md); the escape hatch is `observe.NewLoggerWithRedaction` with the key omitted, a renamed attribute, or `RedactionConfig.Disabled`. No `DEP-` entry (no symbol removed or renamed).
- **BREAKING (CSRF XSRF-cookie config): `EncryptionKey` is mandatory and must be exactly 32 bytes when `EnableXSRFCookie` is `true`.** `pkg/router` is a `stable` surface; this is a deliberate behaviour change per [ADR-006](docs/adrs/ADR-006-csrf-hardening.md). An application that called `CSRFMiddleware` with `EnableXSRFCookie: true` and no (or a non-32-byte) `EncryptionKey` previously started successfully with a weak/truncated key; it now **panics at startup** (or, via `NewCSRFMiddleware`, returns `router.ErrCSRFEncryptionKey`). Migration: set `EncryptionKey` to exactly 32 bytes, sourced from the environment or a secret manager — see `docs/guides/CSRF_GUIDE.md`. Deployments with `EnableXSRFCookie: false` (the default) are unaffected: `EncryptionKey` stays optional and unvalidated for them.
Expand Down
5 changes: 4 additions & 1 deletion contracts/baseline/api_exported_symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ github.com/jcsvwinston/nucleus/pkg/model type:QueryOpts
github.com/jcsvwinston/nucleus/pkg/model type:Registry
github.com/jcsvwinston/nucleus/pkg/model type:SQLQueryEvent
github.com/jcsvwinston/nucleus/pkg/model type:SQLQueryObserver
github.com/jcsvwinston/nucleus/pkg/nucleus const:MaxConfigFileBytes
github.com/jcsvwinston/nucleus/pkg/nucleus field:App.Lifecycle
github.com/jcsvwinston/nucleus/pkg/nucleus field:App.Middleware
github.com/jcsvwinston/nucleus/pkg/nucleus field:App.Modules
Expand Down Expand Up @@ -742,7 +743,9 @@ github.com/jcsvwinston/nucleus/pkg/nucleus type:ServiceRegistration
github.com/jcsvwinston/nucleus/pkg/nucleus type:Shower
github.com/jcsvwinston/nucleus/pkg/nucleus type:Updater
github.com/jcsvwinston/nucleus/pkg/nucleus type:WebhookRegistry
github.com/jcsvwinston/nucleus/pkg/nucleus var:ErrConfigLoaderNotImplemented
github.com/jcsvwinston/nucleus/pkg/nucleus var:ErrConfigFileTooLarge
github.com/jcsvwinston/nucleus/pkg/nucleus var:ErrUnknownConfigKeys
github.com/jcsvwinston/nucleus/pkg/nucleus var:ErrUnsupportedConfigFormat
github.com/jcsvwinston/nucleus/pkg/observe const:RedactionPlaceholder
github.com/jcsvwinston/nucleus/pkg/observe field:RedactionConfig.Disabled
github.com/jcsvwinston/nucleus/pkg/observe field:RedactionConfig.ExtraKeys
Expand Down
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.4
github.com/alexedwards/scs/v2 v2.9.0
github.com/alicebob/miniredis/v2 v2.37.0
github.com/aws/aws-sdk-go-v2/config v1.32.17
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.41.7
github.com/bradfitz/gomemcache v0.0.0-20260422231931-4d751bb6e37c
github.com/casbin/casbin/v2 v2.135.0
github.com/go-playground/validator/v10 v10.25.0
Expand All @@ -18,17 +20,20 @@ require (
github.com/knadh/koanf/parsers/yaml v1.1.0
github.com/knadh/koanf/providers/env v1.1.0
github.com/knadh/koanf/providers/file v1.2.1
github.com/knadh/koanf/providers/rawbytes v1.0.0
github.com/knadh/koanf/providers/structs v1.0.0
github.com/knadh/koanf/v2 v2.1.2
github.com/microsoft/go-mssqldb v1.10.0
github.com/minio/minio-go/v7 v7.0.100
github.com/prometheus/client_golang v1.23.2
github.com/redis/go-redis/v9 v9.14.1
github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v3 v3.24.5
github.com/sijms/go-ora/v2 v2.9.0
go.opentelemetry.io/otel v1.43.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.35.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0
go.opentelemetry.io/otel/exporters/prometheus v0.65.0
go.opentelemetry.io/otel/metric v1.43.0
go.opentelemetry.io/otel/sdk v1.43.0
go.opentelemetry.io/otel/sdk/metric v1.43.0
Expand All @@ -54,15 +59,13 @@ require (
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.41.7 // indirect
github.com/aws/aws-sdk-go-v2/config v1.32.17 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.19.16 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.23 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.23 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.23 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.24 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.9 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.23 // indirect
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.41.7 // indirect
github.com/aws/aws-sdk-go-v2/service/signin v1.0.11 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.30.17 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.21 // indirect
Expand Down Expand Up @@ -116,7 +119,6 @@ require (
github.com/philhofer/fwd v1.2.0 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/client_golang v1.23.2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.67.5 // indirect
github.com/prometheus/otlptranslator v1.0.0 // indirect
Expand All @@ -137,7 +139,6 @@ require (
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.67.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect
go.opentelemetry.io/otel/exporters/prometheus v0.65.0 // indirect
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
go.yaml.in/yaml/v2 v2.4.4 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ github.com/knadh/koanf/providers/env v1.1.0 h1:U2VXPY0f+CsNDkvdsG8GcsnK4ah85WwWy
github.com/knadh/koanf/providers/env v1.1.0/go.mod h1:QhHHHZ87h9JxJAn2czdEl6pdkNnDh/JS1Vtsyt65hTY=
github.com/knadh/koanf/providers/file v1.2.1 h1:bEWbtQwYrA+W2DtdBrQWyXqJaJSG3KrP3AESOJYp9wM=
github.com/knadh/koanf/providers/file v1.2.1/go.mod h1:bp1PM5f83Q+TOUu10J/0ApLBd9uIzg+n9UgthfY+nRA=
github.com/knadh/koanf/providers/rawbytes v1.0.0 h1:MrKDh/HksJlKJmaZjgs4r8aVBb/zsJyc/8qaSnzcdNI=
github.com/knadh/koanf/providers/rawbytes v1.0.0/go.mod h1:KxwYJf1uezTKy6PBtfE+m725NGp4GPVA7XoNTJ/PtLo=
github.com/knadh/koanf/providers/structs v1.0.0 h1:DznjB7NQykhqCar2LvNug3MuxEQsZ5KvfgMbio+23u4=
github.com/knadh/koanf/providers/structs v1.0.0/go.mod h1:kjo5TFtgpaZORlpoJqcbeLowM2cINodv8kX+oFAeQ1w=
github.com/knadh/koanf/v2 v2.1.2 h1:I2rtLRqXRy1p01m/utEtpZSSA6dcJbgGVuE27kW2PzQ=
Expand Down
Loading
Loading