Skip to content

chore(state): close 2026-05-15 MSSQL/Oracle SchemaDrift iteration#68

Merged
jcsvwinston merged 1 commit into
mainfrom
chore/state-close-2026-05-15
May 15, 2026
Merged

chore(state): close 2026-05-15 MSSQL/Oracle SchemaDrift iteration#68
jcsvwinston merged 1 commit into
mainfrom
chore/state-close-2026-05-15

Conversation

@jcsvwinston
Copy link
Copy Markdown
Owner

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

Concurrent in flight

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 #1pkg/admin bootstrap 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 exercised TestSQLMatrix_AutoMigrate_Exploratory. Failures: MSSQL Incorrect syntax near 'nucleus_admin_users', Oracle ORA-03076: unexpected item DEFAULT. Even app.New(cfg, WithoutDefaults()) triggers the admin bootstrap (gated by AdminBootstrapEmail, not by WithoutDefaults). NOTE comments in .github/workflows/ci.yml carry 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.mod and 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 candidatepkg/storage baseline (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

  • Not a code change.
  • Not a CHANGELOG entry (no user-facing behaviour change).
  • Not a contract baseline change.

Test plan

  • CI: full suite passes unchanged (doc + state-only impact).

🤖 Generated with Claude Code

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>
@jcsvwinston jcsvwinston merged commit 8941147 into main May 15, 2026
9 checks passed
@jcsvwinston jcsvwinston deleted the chore/state-close-2026-05-15 branch May 15, 2026 19:05
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant