chore(state): close 2026-05-15 MSSQL/Oracle SchemaDrift iteration#68
Merged
Conversation
PR #66 (MSSQL/Oracle SchemaDrift introspection) and PR #65 (pkg/app + pkg/nucleus inventory) both merged on 2026-05-15. State files refreshed; the SchemaDrift iteration is archived; CURRENT_ITERATION.md candidate queue updated with the discoveries and decisions of the day: - New top-ranked candidate: `pkg/admin` bootstrap users-table DDL fix for MSSQL/Oracle. Discovered as a side-effect during PR #66 CI (admin bootstrap fires even with `WithoutDefaults()`, gated by `AdminBootstrapEmail`). NOTE comments in `.github/workflows/ci.yml` carry the breadcrumb. - Phase 4 AWS SDK opt-in (build-tag path) replaced with Cloud Secrets Provider plugin extraction — same architectural pattern the repo established for SendGrid (DEP-2026-002 / MA-2026-002). Three-iteration project. - `pkg/storage` baseline candidate dropped — already closed during PR #63's coordinated rebaseline. No code changes. No CHANGELOG impact. No public API impact. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
jcsvwinston
added a commit
that referenced
this pull request
May 16, 2026
) Replaces the Phase 1 `ErrConfigLoaderNotImplemented` stub with a real single-file YAML loader, the first slice of ADR-010 §2 (Phase 2 work sliced into 2a / 2b / 2c / 2d sub-iterations). Loader guards (ADR-010 §17 compliance + §2 validation layers 1-2): - **1 MiB per-file size cap** (`MaxConfigFileBytes`) enforced before the YAML parser ever runs — eliminates the anchor-expansion / deep-nesting DoS classes against `gopkg.in/yaml.v3`. Implemented via `io.LimitReader(path, cap+1)`: the +1 detects overshoot so the structured `ErrConfigFileTooLarge` is returned rather than a parser surprise. `os.Stat` is NOT used as the only check (procfs / FUSE can lie about size); reading is the source of truth. - **Extension-based parser inference**. `.yaml` / `.yml` work today via the existing koanf YAML parser. `.toml` / `.json` return `ErrUnsupportedConfigFormat` with a Phase 2b reference; the parsers land alongside the multi-file merge engine. - **Strict-unknown-fields schema validation** against `app.ContractConfigKeyPatterns()`. Two koanf instances are used: one to enumerate the file's keys for the strict check, and a second one for the actual layered load (defaults < file). Unknown keys surface as `ErrUnknownConfigKeys` listing every offending key with did-you-mean hints (Levenshtein distance ≤3 on the final segment). - **Wildcard pattern matching**. `keyMatchesAny` matches a flat koanf key against schema patterns segment-by-segment, with `*` as a single-segment wildcard. Recognises map-typed schema slots like `databases.*.url` and `jwt_keys.*.kid`. Builder integration: - `AppBuilder.FromConfigFile(path)` now invokes the real loader. - Multi-path `FromConfigFile(a, b)` fails fast with a Phase 2b reference — the merge engine is the next sub-PR. - Modules / Middleware / Services / Lifecycle registered BEFORE the `FromConfigFile` call are preserved; only the embedded `app.Config` slot is replaced (regression test included). - `ErrConfigLoaderNotImplemented` is removed entirely — Phase 1 stub retired. Pre-`v1.0` clean break per the ADR-006 / ADR-008 precedent. New exported surface added to the freeze baseline: - const `MaxConfigFileBytes` - var `ErrConfigFileTooLarge` - var `ErrUnsupportedConfigFormat` - var `ErrUnknownConfigKeys` Removed from the freeze baseline: - var `ErrConfigLoaderNotImplemented` (Phase 1 stub) Net delta: +4 / -1 entries in `contracts/baseline/api_exported_symbols.txt`. New dependency: - `github.com/knadh/koanf/providers/rawbytes v1.0.0` — sibling of the YAML provider already in tree. Zero-go, used by the loader to feed the file bytes into koanf without going through the filesystem twice (the first read is constrained by the 1 MiB cap). Tests added in `pkg/nucleus/config_test.go` (13 cases): - Happy-path YAML load - Defaults preserved for unset keys - Unsupported extension rejected (.ini etc.) - TOML/JSON paths return Phase-2b sentinel - File over the cap → ErrConfigFileTooLarge - File exactly at the cap boundary → accepted - Unknown key → ErrUnknownConfigKeys - Did-you-mean hint surfaces for plausible typos - Missing file is reported as a file error, not a content error - Malformed YAML produces a parse error - Empty path rejected - `AppBuilder.FromConfigFile` end-to-end happy path - `AppBuilder.FromConfigFile` preserves Modules mounted earlier - Levenshtein basics - Wildcard pattern matcher (`databases.*.url`, `jwt_keys.*.kid`) Local validation: go build ./... clean; go vet ./... clean; go test ./... green (all 38 pkg/nucleus tests including the 13 new config tests); `bash scripts/ci/check_contract_freeze.sh` green. `go mod tidy` side effects: the AWS SDK config / secretsmanager modules previously annotated `// indirect` are now correctly `// direct` (they are direct deps of `pkg/auth/secrets`); the Prometheus and OpenTelemetry/Prometheus exporter modules used by `pkg/observability` similarly promoted. No functional change, just correctness in `go.mod`. State files and the Phase 1 iteration archive (`docs/iterations/2026-05-16-adr010-phase1-and-examples-purge.md`) are intentionally NOT staged here — they belong to the state-close PR following the convention established by #61 / #64 / #68. Phase 2 sub-PR map: - 2a (this PR) — single-file FromConfigFile + size cap + strict schema. - 2b — multi-file merge + `_append`/`_remove` suffix operators + TOML/JSON parsers + non-nullable security keys. - 2c — `WithUnknownFields("warn")` + `NUCLEUS_ENV=production` strict override + startup WARN. - 2d — migration namespacing in `pkg/db/migrate.go`. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
State-close PR for the 2026-05-15 session. Follows the convention established by #55, #59, #61, #64 — feature PRs ship first, state files close in their own small PR.
Today's merged work
docs(iteration): archive pkg/app + pkg/nucleus inventory pass(Phase 1 input for upcoming Fluent API v2 ADR)feat(db): MSSQL/Oracle SchemaDrift introspection + live-DB CI lanes— closes theErrSchemaDriftUnsupportedsentinel paths; live-DB CI lanes for all four matrix engines pass first-timeConcurrent in flight
chore(meta): refine subagent + slash command definitions(independent; touches.claude/agents/and.claude/commands/)What's in this PR
docs/iterations/2026-05-15-mssql-oracle-schemadrift.md(new) — archive of today's SchemaDrift iteration with the full follow-up list..claude/state/HANDOFF.md— refreshed for the next session..claude/state/CURRENT_ITERATION.md— refreshed; candidate queue reordered with today's discoveries.Key queue updates documented in CURRENT_ITERATION.md
New candidate feat: harden framework baseline for v0.5.5 #1 —
pkg/adminbootstrap users-table DDL fix for MSSQL/Oracle. Real pre-existing bug surfaced when PR feat(db): MSSQL/Oracle SchemaDrift introspection + live-DB CI lanes #66's CI workflow fix finally exercisedTestSQLMatrix_AutoMigrate_Exploratory. Failures: MSSQLIncorrect syntax near 'nucleus_admin_users', OracleORA-03076: unexpected item DEFAULT. Evenapp.New(cfg, WithoutDefaults())triggers the admin bootstrap (gated byAdminBootstrapEmail, not byWithoutDefaults). NOTE comments in.github/workflows/ci.ymlcarry the breadcrumb at the exploratory lanes.New candidate feat(cli): add django-style aliases and parity docs #2 — Cloud Secrets Provider plugin extraction. Replaces the original "Phase 4 AWS SDK opt-in via build tag" plan. Build tags would leave AWS in
go.modand only save link size; plugin extraction (matching the SendGrid precedent — DEP-2026-002 / MA-2026-002) removes AWS deps entirely from the supply chain. Three-iteration project: ADR + contract → extract → deprecate. Skip the build-tag stopgap.Dropped candidate —
pkg/storagebaseline (was audit §7 task 2). Verified already closed during PR feat(router,db): CSRF follow-ups (ADR-008) + schema drift (ADR-009) #63's coordinated rebaseline.What this is NOT
Test plan
🤖 Generated with Claude Code