From c9537ee229610a1d42d3a4b5f2731877a6af52d6 Mon Sep 17 00:00:00 2001 From: JohnnyT Date: Wed, 30 Sep 2026 08:06:19 -0600 Subject: [PATCH] Accepts two 0.7.0 amendments at 1fcb204 Flips the Status lines of ADR-0004's Amendment of 2026-09-29 (a from: of this package's own type that declares legacy: is not silent) and ADR-0005's Amendment B (:root_vault required only when :gcp_kms is absent) from proposed to accepted (2026-09-30), in place. Both code halves shipped in encryptor_ecto 0.7.0 (tag v0.7.0 at 1fcb204), and a dated Note at each record's foot lists what was re-verified there. The records' own Status lines and index rows do not change; the index gains a paragraph naming the two amendments. No line is removed but the two status lines. Refs: ece-vvez --- docs/adr/0004-migration-from-cloak.md | 44 ++++++++++++++++++++- docs/adr/0005-wrapped-key-row-shape.md | 53 +++++++++++++++++++++++++- docs/adr/README.md | 5 +++ 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/docs/adr/0004-migration-from-cloak.md b/docs/adr/0004-migration-from-cloak.md index f794f08..910426a 100644 --- a/docs/adr/0004-migration-from-cloak.md +++ b/docs/adr/0004-migration-from-cloak.md @@ -1082,7 +1082,7 @@ Provenance: bead ece-60gg. ## Amendment (2026-09-29): a `from:` of this package's own type that declares `legacy:` is not silent -Status: proposed (2026-09-29). +Status: accepted (2026-09-30). Decided: ruled by the operator, 2026-09-29. @@ -1154,3 +1154,45 @@ This Note decides nothing: no decision, no amendment's rule and no status word above changes. Provenance: bead ece-qlc. + +## Note (2026-09-30): the Amendment of 2026-09-29 on a `from:` that declares `legacy:` is accepted + +The Status line of the Amendment above, "a `from:` of this package's own +type that declares `legacy:` is not silent", now reads `accepted +(2026-09-30)`. The record's own Status line and its index row, `accepted +(2026-08-27, with amendments)`, do not change. The Note of 2026-09-29 on the +release `eval` lines decides nothing and has no status word to flip. + +The code half shipped in `encryptor_ecto` 0.7.0, the commit tagged `v0.7.0` +(`1fcb204`) and published on Hex; its changelog's `[0.7.0]` section carries +the `**Breaking**` entry for a plan field whose `from:` declares `legacy:`. +Every claim the Amendment makes was re-verified at that commit before the +flip: + +- What was open. `Encryptor.Ecto.Migrator.Source.vault_backed?/2` answers by + the params `Encryptor.Ecto.Binary.init/2` freezes, and `:legacy` is one of + the keys `frozen_params?/1` requires (`@our_params`, + `lib/encryptor/ecto/migrator/source.ex`), so a declaration with `legacy:` + set still answers `true`. The exit guide carries the section "If you must + go back: the reverse plan" (`docs/guides/migrate-from-cloak.md`), and + `Encryptor.Ecto.Binary`'s moduledoc carries "The migration window: + `:legacy`". +- The decision and where it lives. A declared `true` or `false` is returned + as declared (`Encryptor.Ecto.Migration`'s `source_authenticated!/4`); a + field that declared nothing reaches `undeclared_source!/3`, which raises a + `CompileError` (`raise_at!/2`) when `vault_backed?/2` answers `true` and + the frozen params name a `legacy:` module (`legacy_reader/2`). The message + names the schema and the field (`field_at/1`), the `from:` type and the + `legacy:` module (`undeclared_legacy_message/3`). A vault-backed `from:` + whose declaration names no `legacy:` module still compiles silent, to + `true` (the last branch of `undeclared_source!/3`). +- What it does not change. Between `v0.6.0` and `v0.7.0`, `vault_backed?/2` + changes in its doc only, and `@field_options` is unchanged + (`lib/encryptor/ecto/migration.ex`), so its answer is the same and no + field option is added. +- The tests. `test/encryptor/ecto/migration_test.exs` has "refuses a from: + of this package's own type that declares legacy:", "a from: that declares + legacy: compiles once the field declares" and "one of this package's own + types needs no declaration". + +Provenance: bead ece-vvez. diff --git a/docs/adr/0005-wrapped-key-row-shape.md b/docs/adr/0005-wrapped-key-row-shape.md index f76841e..ab86e1e 100644 --- a/docs/adr/0005-wrapped-key-row-shape.md +++ b/docs/adr/0005-wrapped-key-row-shape.md @@ -1114,7 +1114,7 @@ Provenance: bead ece-60gg. ## Amendment B (2026-09-29): `:root_vault` is required only when `:gcp_kms` is absent -Status: proposed. Ruled by the operator, 2026-09-29. No text above this +Status: accepted (2026-09-30). Ruled by the operator, 2026-09-29. No text above this Amendment is edited in place, and no status word above flips. Cites into this package name the function they point at, as it stands in @@ -1297,3 +1297,54 @@ read, destroy the version, delete the row", assert the new term as the commit this Note ships in leaves them. Provenance: bead ece-h9qm. + +## Note (2026-09-30): Amendment B is accepted + +Amendment B's Status line now reads `accepted (2026-09-30)`. The record's own +Status line, `accepted (2026-09-13)`, and its index row, `accepted +(2026-09-13, with amendments)`, do not change. Amendment B's "no status word +above flips" was true of it and stays true: the status word that flips is +its own, and it flips here. The two Notes after it decide nothing and have +no status word to flip. + +The code half shipped in `encryptor_ecto` 0.7.0, the commit tagged `v0.7.0` +(`1fcb204`) and published on Hex; its changelog's `[0.7.0]` section carries +the `Added` entry for a store started without `:root_vault`. Every claim was +re-verified at that commit before the flip, and against `encryptor` `v0.6.0` +(`91e9643`), the release 0.7.0 pins (`{:encryptor, "== 0.6.0"}` in +`mix.exs`, `deps/0`): + +- B1. `Encryptor.Ecto.KeyStore`'s `root_vault/1` answers `{:ok, nil}` when + `:root_vault` is absent and `:gcp_kms` is present, and otherwise defers to + `module_option/2`, which refuses an absent option as `{:missing_config, + [:provider, :root_vault]}` and a value that is not a module as + `{:invalid_config, :root_vault, :not_a_module}`. `root_vault/1` reads only + whether `:gcp_kms` is present; `init/1` then runs `gcp_kms/2`, which + refuses a malformed value in its own terms. The `state/0` type reads + `root_vault: module() | nil`. +- B2. The `%{root_vault: nil}` clause of `unwrap_row/4` matches an + `:engine_message` row whose `key_id` is `nil` and answers + `{:invalid_key_descriptor, {:no_root_vault, "engine_message"}}`; an + engine-message row carrying a `key_id` falls through to the clause that + answers `{:invalid_key_descriptor, :unexpected_key_id}`, as the + `:missing_key_id` clause answers before the GCP delegation. In `encryptor` + 0.6.0, `t:Encryptor.Provider.reason/0` carries `{:invalid_key_descriptor, + term()}` (`lib/encryptor/provider.ex`), so the term widens nothing. + `encryption_key/2` unwraps the newest row only, and the repo test "costs + only the engine-message rows of a mixed scope" asserts the read keeping + the GCP version and the write answering the refusal. +- B3. Once `init/1` has placed it in the state, the root vault is read by + `unwrap_row/4` alone: the engine-message clause unwraps under it, and the + clause B2 adds matches its absence. +- B4. The commit that shipped the code half changes no `wrapping_shape` + value, column or `tenant_ref` derivation in + `lib/encryptor/ecto/key_store.ex`: beside its moduledoc and doc text, its + code changes are the `state/0` type, `init/1`'s call to `root_vault/1`, + `root_vault/1` itself and the new `unwrap_row/4` clause. +- The tests. `test/encryptor/ecto/key_store_test.exs` has the describe block + "init/1's :root_vault, with :gcp_kms set" beside "refuses a missing root + vault", and `test/encryptor/ecto/key_store_repo_test.exs` has the describe + block "a store configured with :gcp_kms and no root vault", over the fake + in `test/support/test_gcp_kms.ex`. + +Provenance: bead ece-vvez. diff --git a/docs/adr/README.md b/docs/adr/README.md index cddd1e5..1fc4f84 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -19,6 +19,11 @@ ADR-0004's Note of 2026-09-24 (Q1, the folded index) and ADR-0005's Amendment A of 2026-09-24 were accepted on 2026-09-24, and ADR-0006 and ADR-0007 with them; each record's foot Note says what was verified. +ADR-0004's Amendment of 2026-09-29 (a `from:` that declares `legacy:`) and +ADR-0005's Amendment B of 2026-09-29 (`:root_vault` optional with `:gcp_kms`) +were accepted on 2026-09-30, once `encryptor_ecto` 0.7.0 shipped them; each +record's foot Note says what was verified. + New ADRs: next number, same three-section format (Context, Decision, Consequences), plus the typespecs and worked-example sections this family's records carry. Pick the number against a freshly fetched remote.