oficina / memoria Public

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>
Paul Campbell pushed by paul@keymail.dev d57249ee7e7ad3b36561b4f1042025963ab572e0 parent ad1a28f
3 files changed, +10 −5
  • MODEL-FALLBACK-PLAN.md +1 −1
  • internal/memoria/config.go +7 −2
  • internal/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) {