Read the TensorX key from the name it already has: MEMORIA_TENSORX_KEY
The model layer read MEMORIA_TENSORX_API_KEY, but the credential was set on the platform weeks ago as MEMORIA_TENSORX_KEY (by hand, for the 2026-09-05 live-key checks) and nothing read it. A platform secret cannot be read back, so using the new name meant fetching the key again and keeping two copies in sync. Reading the existing one means switching the model layer on is MEMORIA_AI=on and nothing else.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 files changed,
+10
−5
MODEL-FALLBACK-PLAN.md+1 −1internal/memoria/config.go+7 −2internal/memoria/model_config_test.go+2 −2
CI passed — run details
CI log
=== vet === go vet ./... === fmt === === test === go test ./... ? amadan.net/oficina/memoria/cmd/memoria [no test files] ok amadan.net/oficina/memoria/internal/memoria 3.204s ok amadan.net/oficina/memoria/internal/memoria/chunk 0.004s ok amadan.net/oficina/memoria/internal/memoria/fact 0.510s ? amadan.net/oficina/memoria/internal/memoria/icons [no test files] ok amadan.net/oficina/memoria/internal/memoria/index 0.033s ok amadan.net/oficina/memoria/internal/memoria/notion 0.021s ok amadan.net/oficina/memoria/internal/memoria/provider 1.131s ok amadan.net/oficina/memoria/internal/memoria/query 0.004s ok amadan.net/oficina/memoria/internal/memoria/seal 0.004s ok amadan.net/oficina/memoria/internal/memoria/sibling 3.022s ok amadan.net/oficina/memoria/internal/memoriatest 1.559s ? amadan.net/oficina/memoria/scripts/writeestilo [no test files] ? amadan.net/oficina/memoria/tools/bench [no test files] ? amadan.net/oficina/memoria/tools/drive [no test files] ? amadan.net/oficina/memoria/tools/seed [no test files] ? amadan.net/oficina/memoria/tools/vendorassets [no test files] === migration-check === go run github.com/carlosframework/rastrillo/cmd/rastrillo migration check rastrillo migration check: models and migrations agree
diff --git a/MODEL-FALLBACK-PLAN.md b/MODEL-FALLBACK-PLAN.md| index 77c964b..7287816 100644 |
| --- a/MODEL-FALLBACK-PLAN.md |
| +++ b/MODEL-FALLBACK-PLAN.md |
| @@ -97,7 +97,7 @@ The only code in memoria that dials a model. |
| - `MEMORIA_AI` — `on` or unset. Decision 4: opt-in per team, the owner's |
| choice. Anything other than `on` or empty is a startup error, so a typo |
| does not silently mean off. |
| -- `MEMORIA_TENSORX_API_KEY` — required when `MEMORIA_AI=on`, **refused at |
| +- `MEMORIA_TENSORX_KEY` — required when `MEMORIA_AI=on`, **refused at |
| startup** if AI is on and it is absent (loud), and ignored when AI is |
| off. A key present with AI off does not turn AI on. |
diff --git a/internal/memoria/config.go b/internal/memoria/config.go| index 9d174fd..7950722 100644 |
| --- a/internal/memoria/config.go |
| +++ b/internal/memoria/config.go |
| @@ -111,8 +111,13 @@ func LoadConfig(getenv func(string) string) (Config, error) { |
| case "": |
| case "on": |
| c.AI = true |
| - if c.TensorXKey = getenv("MEMORIA_TENSORX_API_KEY"); c.TensorXKey == "" { |
| - return c, fmt.Errorf("%w: MEMORIA_TENSORX_API_KEY (MEMORIA_AI=on names a provider but gives no credential for it)", ErrMissing) |
| + // MEMORIA_TENSORX_KEY, because that is the name the credential was |
| + // already given on the platform (set by hand for the 2026-09-05 |
| + // live-key checks). This code first read MEMORIA_TENSORX_API_KEY, |
| + // which would have meant a second copy of the key under a new name — |
| + // and a platform secret cannot be read back to make one. |
| + if c.TensorXKey = getenv("MEMORIA_TENSORX_KEY"); c.TensorXKey == "" { |
| + return c, fmt.Errorf("%w: MEMORIA_TENSORX_KEY (MEMORIA_AI=on names a provider but gives no credential for it)", ErrMissing) |
| } |
| default: |
| return c, fmt.Errorf("memoria: MEMORIA_AI must be \"on\" or unset; refusing to guess what %q means", ai) |
diff --git a/internal/memoria/model_config_test.go b/internal/memoria/model_config_test.go| index c169509..1139e84 100644 |
| --- a/internal/memoria/model_config_test.go |
| +++ b/internal/memoria/model_config_test.go |
| @@ -34,7 +34,7 @@ func TestTheModelSwitch(t *testing.T) { |
| // Presence of a credential is not consent; the switch is. |
| {"a key with AI unset is still off", "", "k", false, ""}, |
| {"on with a key is on", "on", "k", true, ""}, |
| - {"on without a key is refused", "on", "", false, "MEMORIA_TENSORX_API_KEY"}, |
| + {"on without a key is refused", "on", "", false, "MEMORIA_TENSORX_KEY"}, |
| // A typo must not be read as either answer. |
| {"'true' is refused, not on", "true", "k", false, "MEMORIA_AI"}, |
| {"'On' is refused, not on", "On", "k", false, "MEMORIA_AI"}, |
| @@ -42,7 +42,7 @@ func TestTheModelSwitch(t *testing.T) { |
| } { |
| t.Run(c.name, func(t *testing.T) { |
| env := baseEnv() |
| - env["MEMORIA_AI"], env["MEMORIA_TENSORX_API_KEY"] = c.ai, c.key |
| + env["MEMORIA_AI"], env["MEMORIA_TENSORX_KEY"] = c.ai, c.key |
| cfg, err := LoadConfig(func(k string) string { return env[k] }) |
| if c.wantErr != "" { |
| if err == nil || !strings.Contains(err.Error(), c.wantErr) { |