Skip to content

fix(secrets): collect persona-level TTS provider SecretRefs#89636

Open
SebTardif wants to merge 3 commits into
openclaw:mainfrom
SebTardif:fix/tts-persona-secretref
Open

fix(secrets): collect persona-level TTS provider SecretRefs#89636
SebTardif wants to merge 3 commits into
openclaw:mainfrom
SebTardif:fix/tts-persona-secretref

Conversation

@SebTardif

@SebTardif SebTardif commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

Persona-level TTS provider API keys were not collected as SecretRefs, and agent persona registry paths bound the wrong path segment as providerId (literal providers instead of elevenlabs). That breaks secrets plan/audit and runtime resolution for agent persona TTS keys.

Fixes #89607

Summary

The secret collector walks top-level TTS provider API keys but did not walk persona-level provider keys under tts.personas.*.providers.*.apiKey or agents.entries.*.tts.personas.*.providers.*.apiKey. When a persona overrides the TTS provider config with a file-source SecretRef, the secret resolver never saw the ref, so the apiKey reached the plugin as an unresolved object instead of the actual key string. The plugin then reported not configured.

This fix:

  • Adds persona-level provider iteration in collectTtsApiKeyAssignments
  • Registers persona target paths in the secret target registry (tts.personas.*.providers.*.apiKey and agents.entries.*.tts.personas.*.providers.*.apiKey)
  • Extends agent-runtime target sets to detect persona-level TTS refs
  • Fixes registry providerId binding so persona paths resolve to the provider key (e.g. elevenlabs)
  • Adds regression coverage for top-level, persona-level, nested, empty-persona, and agent-level persona paths
  • Classifies tts.personas.* in exec SecretRef id parity sampling (CI)

Closes #89607

Evidence

Live OpenClaw CLI on branch head c8b15b5f5f4 with an isolated config that uses file-source SecretRefs for persona TTS keys. secrets audit reports status: clean when the secrets file is mode 600. With intentionally open secrets permissions, audit lists all three collected paths (provider, persona, agent-entry persona). infer tts convert --local resolves those SecretRefs locally and reaches the ElevenLabs HTTP API (401 invalid key with a dummy secret), which proves resolution instead of the pre-fix not configured failure.

Real behavior proof

Behavior addressed: Persona-level TTS provider SecretRefs under tts.personas and agents.entries.*.tts.personas must be collected, audited, and resolved so TTS conversion receives a string API key rather than an unresolved SecretRef object.
Real environment tested: macOS, OpenClaw branch fix/tts-persona-secretref at /tmp/oc-89636 commit c8b15b5 (includes parity classify fix; rebased on current main). Isolated state dir /tmp/oc-proof-state-89636 with file secrets provider (dummy key only; never a real credential).
Exact steps or command run after this patch:
Step 1. Configured tts.providers, tts.personas.narrator.providers, and agents.entries.main.tts.personas.narrator.providers with file SecretRefs (source file, provider default, id /elevenlabsNarratorKey) and a mode=json secrets file with mode 600.
Step 2. Audited secret collection and resolvability:

export OPENCLAW_CONFIG_PATH=/tmp/oc-proof-state-89636/openclaw.json
export OPENCLAW_STATE_DIR=/tmp/oc-proof-state-89636/state
node scripts/run-node.mjs secrets audit --json

Step 3. Ran local TTS conversion so runtime resolution must supply the persona/provider key:

node scripts/run-node.mjs infer tts convert --local --text 'hello proof' --json --output /tmp/proof-89636-tts.wav

Evidence after fix: terminal output from the patched CLI at current head c8b15b5.

Secrets audit clean with resolvability complete:

$ node scripts/run-node.mjs secrets audit --json
{
  "version": 1,
  "status": "clean",
  "resolution": {
    "refsChecked": 1,
    "skippedExecRefs": 0,
    "resolvabilityComplete": true
  },
  "filesScanned": [
    "/tmp/oc-proof-state-89636/openclaw.json"
  ],
  "summary": {
    "plaintextCount": 0,
    "unresolvedRefCount": 0,
    "shadowedRefCount": 0,
    "legacyResidueCount": 0
  },
  "findings": []
}

Path-collection diagnostic with intentionally open secrets file permissions (mode 644) lists all three collected paths as unresolved with the same permission error, proving persona jsonPaths enter the collection set:

status: unresolved
tts.providers.elevenlabs.apiKey
tts.personas.narrator.providers.elevenlabs.apiKey
agents.entries.main.tts.personas.narrator.providers.elevenlabs.apiKey

TTS convert resolves SecretRefs locally then reaches ElevenLabs with a string key (dummy key only):

$ node scripts/run-node.mjs infer tts convert --local --text 'hello proof' --json --output /tmp/proof-89636-tts.wav
[secrets] infer tts convert: gateway secrets.resolve unavailable (gateway secrets.resolve requires credentials before opening a websocket
Fix: configure gateway.auth token/password, pair this device, or pass --token/--password.
Config: /tmp/oc-proof-state-89636/openclaw.json); resolved command secrets locally.
Error: TTS conversion failed: elevenlabs: ElevenLabs API error (401): Invalid API key [type=authentication_error, code=unauthorized]

Observed result after fix: secrets audit is clean when secrets are mode 600. Persona paths are collected. Local convert resolves SecretRefs and reaches ElevenLabs authentication with the dummy key (401 Invalid API key), proving a string key was delivered rather than an unresolved object.
What was not tested: Live Gateway websocket secrets.resolve with a paired device token; production ElevenLabs synthesis with a real paid key.

@SebTardif
SebTardif requested a review from a team as a code owner June 2, 2026 23:54
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: M proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 2, 2026
@clawsweeper

clawsweeper Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 18, 2026, 2:21 PM ET / 18:21 UTC.

Summary
The branch adds persona-level TTS provider SecretRef collection, registry and command-target entries, runtime detection, generated credential-surface records, and regression coverage.

PR surface: Source +74, Tests +175, Docs +16. Total +265 across 12 files.

Reproducibility: yes. in source: the linked report provides a concrete file-SecretRef persona configuration, and the proposed collector/registry additions directly cover its previously omitted paths. A full current-head provider conversion was not demonstrated in the supplied evidence.

Review metrics: 1 noteworthy metric.

  • Persona credential targets: 2 added target paths. Both global and agent-level persona TTS API-key paths must participate consistently in secret planning, audit, command policy, and runtime collection.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #89607
Summary: This PR is the explicit candidate fix for the concrete persona-level SecretRef resolution bug in the linked canonical report; the merged optional-TTS startup work is related but distinct.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🐚 platinum hermit
Result: blocked until stronger real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted current-head infer tts convert or Gateway output using a file-source persona SecretRef.
  • Show the provider receives a resolved value or reaches the expected authenticated provider result without exposing credentials.

Proof guidance:

  • [P1] Needs stronger real behavior proof before merge: The redacted terminal probes show direct registry and collector behavior, but not the reported current-head file-SecretRef-to-provider TTS conversion or Gateway runtime path; please redact credentials and private endpoints in any live output. Updating the PR body with that proof should trigger a fresh review, or a maintainer can comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] Without a redacted live openclaw infer tts convert or Gateway run using a file-source persona SecretRef at the current head, a remaining handoff gap between collection, resolution, and the TTS plugin could still be missed.

Maintainer options:

  1. Add current-head runtime proof (recommended)
    Run a redacted openclaw infer tts convert or Gateway TTS scenario with a file-source persona SecretRef and show that the resolved provider is used after the current head commit.
  2. Pause for a provider-capable environment
    Keep the branch open until a contributor or maintainer can supply redacted end-to-end evidence from a real TTS credential setup.

Next step before merge

  • [P1] The only remaining merge gate is contributor-supplied live provider proof, which an automated repair lane cannot credibly create without the affected credential setup.

Security
Cleared: The diff adds no dependency, workflow, permission, secret-exposure, or supply-chain change; it only expands existing SecretRef discovery and target metadata.

Review details

Best possible solution:

Keep the common collector and registry approach, then add redacted current-head proof that a persona-level file SecretRef reaches a real TTS conversion path and produces the expected provider outcome.

Do we have a high-confidence way to reproduce the issue?

Yes in source: the linked report provides a concrete file-SecretRef persona configuration, and the proposed collector/registry additions directly cover its previously omitted paths. A full current-head provider conversion was not demonstrated in the supplied evidence.

Is this the best way to solve the issue?

Yes, conditionally: extending the existing shared secret collector and target registry is the narrowest maintainable fix rather than adding TTS-plugin-specific resolution. The remaining need is end-to-end proof of that shared path.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against b7f99d0ffd2a.

Label changes

Label justifications:

  • P2: The change addresses a bounded optional-TTS credential-resolution defect with limited blast radius.
  • merge-risk: 🚨 auth-provider: Merging changes the SecretRef resolution surface that supplies TTS provider credentials at runtime, while end-to-end provider delivery remains unproven.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The redacted terminal probes show direct registry and collector behavior, but not the reported current-head file-SecretRef-to-provider TTS conversion or Gateway runtime path; please redact credentials and private endpoints in any live output. Updating the PR body with that proof should trigger a fresh review, or a maintainer can comment @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +74, Tests +175, Docs +16. Total +265 across 12 files.

View PR surface stats
Area Files Added Removed Net
Source 6 103 29 +74
Tests 4 175 0 +175
Docs 2 16 0 +16
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 12 294 29 +265

What I checked:

Likely related people:

  • snowzlmbot: Authored the merged optional-TTS SecretRef owner-isolation work that established the adjacent runtime behavior this collector must feed. (role: recent area contributor; confidence: medium; commits: 17c2ce05d80a; files: src/secrets/runtime-config-collectors-tts.test.ts, src/secrets/runtime-config-collectors-tts.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (36 earlier review cycles; latest 8 shown)
  • reviewed 2026-07-15T02:07:38.869Z sha 924532e :: needs real behavior proof before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-15T03:18:39.079Z sha 924532e :: needs real behavior proof before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-15T04:31:40.048Z sha 924532e :: needs real behavior proof before merge. :: [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-15T05:50:54.458Z sha 924532e :: needs real behavior proof before merge. :: [P1] Integrate persona collection before the current-main return | [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-16T12:50:14.236Z sha 9d99019 :: needs real behavior proof before merge. :: [P1] Move persona collection before the current-main return | [P3] Remove the release-owned changelog entry
  • reviewed 2026-07-18T12:11:28.608Z sha 2ff6193 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-18T12:16:19.092Z sha 2ff6193 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-18T18:14:05.783Z sha 41d4bdc :: needs real behavior proof before merge. :: none

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. labels Jun 3, 2026
@openclaw-barnacle openclaw-barnacle Bot added the docs Improvements or additions to documentation label Jun 3, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 3, 2026
@openclaw-barnacle openclaw-barnacle Bot added the cli CLI command changes label Jun 3, 2026
@SebTardif
SebTardif force-pushed the fix/tts-persona-secretref branch from 631a4e8 to 9c158e5 Compare June 3, 2026 19:25
@clawsweeper

clawsweeper Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

@SebTardif thanks for the PR. ClawSweeper is still waiting on real behavior proof before this can move forward.

Useful proof can be a screenshot, short video, terminal output, copied live output, linked artifact, or redacted logs that show the changed behavior after the fix. Please redact private tokens, phone numbers, private endpoints, customer data, and anything else sensitive.

Once proof is added to the PR body or a comment, ClawSweeper or a maintainer can re-check it.

@SebTardif

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Addressed the P1 agent-runtime target gap: messages.tts.personas.*.providers.*.apiKey is now in STATIC_AGENT_RUNTIME_BASE_TARGET_IDS with coverage assertions for both global and agent-level persona paths.

@clawsweeper

clawsweeper Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 9, 2026
@SebTardif

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Fixed providerIdPathSegmentIndex for agent persona TTS (6→7) and agent TTS providers (4→5), added registry assertions, and refreshed terminal proof of providerId=elevenlabs plus persona file SecretRef collection. Live ElevenLabs synthesis still not available here; #101204 remains the fail-open product decision.

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. labels Jul 14, 2026
@SebTardif
SebTardif force-pushed the fix/tts-persona-secretref branch 2 times, most recently from 9d99019 to 2ff6193 Compare July 18, 2026 12:08
@SebTardif

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@SebTardif

Copy link
Copy Markdown
Contributor Author

Rebased onto current main and addressed the integration findings:

  1. Persona collection now sits after top-level providers in collectTtsApiKeyAssignments on the post-rebase API (collectRuntimeSecretInputAssignment + TTS capability owner). There is no early return that skips personas.
  2. Removed the CHANGELOG.md edit (release-owned).
  3. Squashed to a single commit on latest main.

Local proof (unit/registry, exact head after rebase):

$ pnpm exec vitest run src/secrets/runtime-config-collectors-tts.test.ts src/secrets/target-registry.test.ts src/cli/command-secret-targets.test.ts
Test Files  3 passed (3)
Tests  57 passed (57)

Still not available here: live Gateway TTS synthesis with a real provider credential. Collector and registry paths are covered by tests and the previous terminal probes.

@clawsweeper clawsweeper Bot removed the merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. label Jul 18, 2026
@SebTardif
SebTardif force-pushed the fix/tts-persona-secretref branch from 2ff6193 to 41d4bdc Compare July 18, 2026 18:10
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 18, 2026
@SebTardif

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Updated the PR body with a live file-source persona SecretRef path: isolated config + secrets audit status clean, then infer tts convert --local resolved command secrets locally and reached ElevenLabs (401 invalid dummy key), which shows resolution instead of the old unresolved/not configured path.

@clawsweeper

clawsweeper Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@SebTardif
SebTardif force-pushed the fix/tts-persona-secretref branch from 17b6784 to b49daf3 Compare July 24, 2026 11:43
@SebTardif

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Refreshed onto current main with tts/agents.entries path schema. Re-ran secrets audit (clean) and infer tts convert (local resolve then ElevenLabs 401). Persona jsonPaths confirmed in collection set.

@clawsweeper

clawsweeper Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

@clawsweeper

clawsweeper Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper status: review started.

I am starting a fresh review of this pull request: fix(secrets): collect persona-level TTS provider SecretRefs This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

Walk tts.personas.*.providers.*.apiKey (and agents.entries.*.tts.personas)
when collecting runtime SecretRefs so persona overrides resolve like top-level
TTS providers. Registers audit/configure targets and CLI secret-policy ids
for the current tts / agents.entries path schema.

Refreshed onto current main (paths no longer use messages.tts / agents.list).

Signed-off-by: Sebastien Tardif <[email protected]>
Keep secretref-user-supplied-credentials-matrix.json in registry order so
target-registry.docs tests stay green after persona SecretRef targets.

Signed-off-by: Sebastien Tardif <[email protected]>
The persona-level TTS registry entry was unclassified, so the sampled
class coverage test failed with tts.personas.*.providers.*.apiKey.
Treat tts.personas.* the same class as tts.providers.*.

Signed-off-by: Sebastien Tardif <[email protected]>
@SebTardif
SebTardif force-pushed the fix/tts-persona-secretref branch from a044bc6 to c8b15b5 Compare July 24, 2026 12:54
@SebTardif

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Refreshed live proof on current head c8b15b5 (post parity-classify CI fix):

  • secrets audit clean with mode-600 file SecretRef
  • open-perms diagnostic lists provider + persona + agent-entry persona paths
  • infer tts convert --local resolves secrets and reaches ElevenLabs 401 (string key delivered)

@clawsweeper

clawsweeper Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling cli CLI command changes docs Improvements or additions to documentation merge-risk: 🚨 auth-provider 🚨 May break OAuth, tokens, provider routing, model choice, or credentials. P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: S status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Secret resolver does not inject file-source secrets into ElevenLabs TTS provider at runtime

1 participant