Skip to content

Add a runtime override layer for one request or job - #22

Merged
imanimanyara merged 2 commits into
mainfrom
feat/runtime-overrides
Nov 14, 2026
Merged

imanimanyara merged 2 commits into
mainfrom
feat/runtime-overrides

Conversation

@imanimanyara

Copy link
Copy Markdown
Member

Summary

Adds a runtime override layer: an in-memory value for a setting that lasts one request or job. It wins over every stored layer, and it is never written, cached, versioned, audited or encrypted.

API (on the contract, SettingsManager, SettingsFake and the facade):

  • override(string|array $key, $value = null)
  • forgetOverride($key)
  • hasOverride($key)
  • clearOverrides()
  • withOverrides(array, callable): restores the previous overrides in finally, including when the callback throws, and nests.

Design:

  • Lifetime: one #[Scoped] Services\Resolution\Overrides, so overrides end with the request or job, under Octane too. It is keyed by store, scope, key and locale, and split per tenant.
  • Precedence: the Resolver checks overrides first, along the same owner → parents → global walk. With no overrides held, the lookup path, the queries and the behaviour are all unchanged.
  • Values: checked and cast by ValuePipeline::inMemory(), including values.max_bytes.
  • Locks and precedence: an override wins over a locked setting and over file/config precedence, by design; this is documented.
  • Permissions: setting an override needs no write ability, since nothing durable changes. Reads still check view and view_sensitive.
  • REST: no route exposes overrides, and a test asserts it.
  • Visibility: explain() reports the layer override, and laranail::settings.show adds an Override row.
  • Typed settings: save() skips a property whose value came from an override, unless it changed.

Docs

  • docs/tools/runtime-overrides.md: a full reference.
  • docs/recipes/overriding-a-setting-for-one-request.md: middleware, a queued job, and a feature-flag switch.
  • The architecture page's lookup section and Mermaid diagram, the API reference, the testing recipe, getting-started, commands, runtime-configuration, the README index and the CHANGELOG.

Verification (local)

  • 28 new tests. Two were shown to fail when their fix was undone: dropping finally from withOverrides, and binding the overrides store as a singleton.
  • Pest: 741 passed. PHPStan, Rector and Pint: clean.

Copilot AI balanced review requested due to automatic review settings November 14, 2026 10:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@imanimanyara
imanimanyara merged commit ad2a9b3 into main Nov 14, 2026
14 checks passed
@imanimanyara
imanimanyara deleted the feat/runtime-overrides branch November 14, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants