Problem/Motivation
The settings form at /admin/config/content/content-credentials explains that the service API key is deliberately not a form field, because Drupal configuration is exported to code and usually committed, and tells the site builder to set it in settings.php instead. It then reports:
Currently: no key is set.
— while the key is set, in that very file, and is the one the reader actually uses.
Steps to reproduce
- Add to
settings.php:$config['content_credentials.settings']['reader']['api_key'] = 'something'; - Rebuild caches.
- Open
/admin/config/content/content-credentials.
The page says no key is set. \Drupal::config('content_credentials.settings')->get('reader.api_key') returns the value.
Measured on Drupal 11.4.6 with ai_disclosure 1.0.0-alpha2, on the site built to exercise the HTTP signing-service route.
Cause
SettingsForm::apiKeyNote() reads $this->config(...). That is ConfigFormBase's editable configuration object, and overrides from settings.php are not applied to it. The form never writes reader.api_key — on purpose — so the stored value is empty on every site, and the line therefore reads "no key is set" whatever the site has done.
The form already knows this distinction. withOverrideState() compares configFactory()->getEditable() against configFactory()->get() for exactly this reason, and carries a comment saying that editable configuration "has no overrides applied — comparing it against itself could never detect one". The API-key note did not get the same treatment, and its own docblock says it reports "whether one is in effect".
Proposed resolution
Read the effective value — configFactory()->get(...) — for that one line.
Two things the fix must not do, and both are worth a test rather than care:
- It must never render the key itself, or any part of it. The line says whether a key is in effect and nothing more. A fix that helpfully shows the first few characters would turn a wrong sentence into a credential leak on a page that a site builder may screenshot.
- It must not turn the key into a form field, or write it to configuration. Keeping it out of exported config is the whole reason the paragraph exists.
Remaining tasks
- A failing test with the value present only as an override, watched failing.
- The fix.
- A test that the key itself never reaches the rendered page.
User interface changes
One sentence on the settings form starts telling the truth.
API changes
None.
Data model changes
None.
Note on how this was found
By running the module on a real site with the key where the form says it belongs. It is not reachable from a configuration fixture, because settings.php is not configuration — which is why the existing tests cover the override machinery and still miss this line.
Comments
Comment #4
maurice1969 commentedFixed in 1aeae2c, on
mainand1.0.x.apiKeyNote()reads the effective configuration instead ofConfigFormBase's editable object. One call. The form already knew the distinction —withOverrideState()compares editable against effective for exactly this reason and says so in a comment — and this line had simply not been given the same treatment, while its own docblock claimed it reported whether a key is "in effect".What was measured
settings.php, and the key appears nowhere in the page source.ai_disclosure1.0.0-alpha2. CI green on both branches, read job by job.One note worth passing on, because it nearly cost a wrong conclusion: the first attempt at the third mutation reported a pass, and the test was not at fault — the substitution had silently failed to match, so the code under test never changed. A mutation that does not apply looks exactly like a test that does not bind. Confirm the source actually changed before believing a survivor.
Marking fixed.