Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Removed

- **Breaking, for 0.4.0: the runtime settings store.** `Toolkit::settings()`, `Laranail::settings()`,
`Services\SettingsStore`, `Services\Contracts\SettingsStoreInterface`, their container bindings,
the `laranail.toolkit.settings` config block and its env keys `LARANAIL_SETTINGS_DISK` and
`LARANAIL_SETTINGS_PATH` are removed, with no forwarder. Runtime settings now live in
`laranail/settings`, added to `suggest`. Move the JSON file's data with
`php artisan laranail::settings.import <absolute path> --from=toolkit --apply` (a dry run without
`--apply`); see [UPGRADING.md](UPGRADING.md). `isValidDatabaseConnection('settings')`,
`RuntimeConfigurator` and the feature toggles are unaffected.

## [0.3.2] - 2026-10-20

### Changed
Expand Down
38 changes: 38 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,43 @@
# Upgrade guide

## The settings store moved to `laranail/settings` (0.4.0)

Toolkit's JSON-file settings store is gone. Runtime settings now live in
[`laranail/settings`](https://opensource.simtabi.com/documentation/laranail/settings/), which stores
them in the database with types, scopes and encryption. This is a breaking change, shipping in 0.4.0.

Removed, with no forwarder:

- `Toolkit::settings()` and `Laranail::settings()`;
- `Simtabi\Laranail\Toolkit\Services\SettingsStore` and
`Services\Contracts\SettingsStoreInterface`, and their container bindings;
- the `laranail.toolkit.settings` config block (`disk`, `path`) and its env keys
`LARANAIL_SETTINGS_DISK` and `LARANAIL_SETTINGS_PATH`. Delete them from your `.env` and from a
published `config/laranail/toolkit.php`.

Move the data before you upgrade. The file defaulted to `laranail/settings.json` on the `local`
disk, so it is usually `storage/app/laranail/settings.json`. The importer reads a local absolute
path; if the file sat on another disk (for example `s3`), copy it down first.

```bash
composer require laranail/settings
php artisan laranail::settings.import /var/www/storage/app/laranail/settings.json --from=toolkit # a dry run
php artisan laranail::settings.import /var/www/storage/app/laranail/settings.json --from=toolkit --apply
```

The importer flattens nested objects to dot keys (`{"mail": {"host": …}}` becomes `mail.host`) and
keeps a list as one value. Then replace the calls:

```diff
- Toolkit::settings()->get('mail.host', 'localhost');
- Toolkit::settings()->set('mail.host', $host);
+ Settings::get('mail.host', 'localhost');
+ Settings::set('mail.host', $host);
```

See the settings package's importer and usage docs for keys that must be defined before they are
set, and for scoped values.

## Atlas, Avatar and Gravatar moved out

Three modules left this package. `Modules\Atlas` became
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@
"livewire/livewire": "^3.0 \u2014 for the Livewire component-registration module",
"laranail/db-tools": "for UUID/ULID model traits, schema macros, soft-archive, backup/restore and the database CLI (relocated out of this package)",
"laranail/package-tools": "for the fluent runtime ConfigManager, relocated out of this package.",
"laranail/python": "Bidirectional Python bridge \u2014 HTTP services, local process execution and signed callbacks (supersedes PythonApiService, relocated out of this package)."
"laranail/python": "Bidirectional Python bridge \u2014 HTTP services, local process execution and signed callbacks (supersedes PythonApiService, relocated out of this package).",
"laranail/settings": "Typed, scoped, database-backed runtime settings (replaces the removed SettingsStore; import its JSON file with laranail::settings.import --from=toolkit)."
},
"repositories": [
{
Expand Down
9 changes: 0 additions & 9 deletions config/toolkit.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,6 @@
],
],

/*
* Runtime settings store (Services\SettingsStore) — a JSON file of dynamic,
* persisted-at-runtime values, kept separate from this static config.
*/
'settings' => [
'disk' => env('LARANAIL_SETTINGS_DISK', 'local'),
'path' => env('LARANAIL_SETTINGS_PATH', 'laranail/settings.json'),
],

/*
* PHP runtime / INI settings applied by Support\RuntimeConfigurator via
* ->usingConfig()/::fromConfig(). Everything here is data — override any
Expand Down
5 changes: 2 additions & 3 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ src/
├── Commands/MakeCrud.php # make-crud (extends the laranail/console base)
├── Http/Controllers/CrudController.php # abstract base controller
├── Services/ # injectable, interface-backed services (File, System,
│ # Cache, Log, SettingsStore, RateLimiter, Scheduler, ...)
│ # Cache, Log, RateLimiter, Scheduler, ...)
├── Macros/ # grouped macro providers + MacroServiceProvider
├── Traits/ # ApiResponse, Auditable, FilePathGuard, ...
├── Support/ # pure/static helpers: ApiResponder, Cast, Config, AuthHelper,
Expand Down Expand Up @@ -86,14 +86,13 @@ or the unified `Toolkit` facade (`Toolkit::archiver()`, …).
injectable core services with typed `@method` accessors. Alongside the module
accessors (`archiver()`, `cache()`,
`livewire()`) and the security generators (`token()`, `password()`,
`passphrase()`), it exposes the core services — including the **five service
`passphrase()`), it exposes the core services — including the **four service
accessors**:

| Accessor | Returns (contract) |
|---|---|
| `Toolkit::cache()` | `Services\Contracts\CacheRepositoryInterface` |
| `Toolkit::log()` | `Services\Contracts\LoggerServiceInterface` |
| `Toolkit::settings()` | `Services\Contracts\SettingsStoreInterface` |
| `Toolkit::rateLimiter()` | `Services\Contracts\RateLimiterServiceInterface` |
| `Toolkit::scheduler()` | `Services\Contracts\SchedulerServiceInterface` |

Expand Down
10 changes: 0 additions & 10 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,6 @@ Named profiles live under `defaults.<name>`, each a `{max_attempts, decay_minute
| `defaults.auth` | `5` | `15` |
| `defaults.download` | `3` | `1` |

## `laranail.toolkit.settings`

The runtime settings store (`SettingsStore`) — a JSON file of dynamic,
persisted-at-runtime values, kept separate from this static config.

| Key | Default | Notes |
|-----|---------|-------|
| `disk` | `local` | Filesystem disk for the settings file. Env: `LARANAIL_SETTINGS_DISK`. |
| `path` | `laranail/settings.json` | Path on the disk. Env: `LARANAIL_SETTINGS_PATH`. |

## `laranail.toolkit.runtime`

PHP runtime / INI settings applied by
Expand Down
4 changes: 2 additions & 2 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ php artisan migrate

These are resolved from the package and need **no** `vendor:publish`:

- **Services** — `Services\{CacheService, SettingsStore, SchedulerService,
RateLimiterService, LogService}` (container-bound by their contracts + concrete
- **Services** — `Services\{CacheService, SchedulerService, RateLimiterService,
LogService}` (container-bound by their contracts + concrete
class; inject or `app(...)` them).
- **Support helpers** — `Support\{QueryParameters, CollectionFilter, Environment,
AuthHelper}` (static utilities).
Expand Down
15 changes: 0 additions & 15 deletions docs/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,21 +69,6 @@ Level methods: `debug()`, `info()`, `warning()`, `error()`, `critical()` (each
`(string $message, array $context = [], ?string $channel = null)`), plus the
enum-keyed `log(LogLevel $level, ...)` and `exception(Throwable $e, ...)`.

### SettingsStore

Read/write dynamic settings persisted as a JSON file on a configured disk — a
runtime store, deliberately separate from Laravel's static `config()`. Keys use
dot notation. Bound to `Services\Contracts\SettingsStoreInterface`.

```php
$settings = app(SettingsStore::class);
$settings->all();
$settings->get('feature.enabled', false);
$settings->has('feature.enabled');
$settings->set('feature.enabled', true);
$settings->forget('feature.enabled');
```

### RateLimiterService

Thin wrapper over Laravel's rate limiter. Bound to
Expand Down
1 change: 0 additions & 1 deletion src/Facades/Laranail.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
* @method static \Simtabi\Laranail\Toolkit\Services\Contracts\CacheRepositoryInterface cache()
* @method static \Simtabi\Laranail\Toolkit\Support\RuntimeConfigurator runtime()
* @method static \Simtabi\Laranail\Toolkit\Services\Contracts\LoggerServiceInterface log()
* @method static \Simtabi\Laranail\Toolkit\Services\Contracts\SettingsStoreInterface settings()
* @method static \Simtabi\Laranail\Toolkit\Services\Contracts\RateLimiterServiceInterface rateLimiter()
* @method static \Simtabi\Laranail\Toolkit\Services\Contracts\SchedulerServiceInterface scheduler()
* @method static \Simtabi\Laranail\Toolkit\Modules\Livewire\LivewireServiceInterface livewire()
Expand Down
1 change: 0 additions & 1 deletion src/Facades/Toolkit.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
* @method static \Simtabi\Laranail\Toolkit\Macros\MacroableModels macroableModels()
* @method static \Simtabi\Laranail\Toolkit\Support\RuntimeConfigurator runtime()
* @method static \Simtabi\Laranail\Toolkit\Services\Contracts\LoggerServiceInterface log()
* @method static \Simtabi\Laranail\Toolkit\Services\Contracts\SettingsStoreInterface settings()
* @method static \Simtabi\Laranail\Toolkit\Services\Contracts\RateLimiterServiceInterface rateLimiter()
* @method static \Simtabi\Laranail\Toolkit\Services\Contracts\SchedulerServiceInterface scheduler()
* @method static \Simtabi\Laranail\Toolkit\Modules\Livewire\LivewireServiceInterface livewire()
Expand Down
7 changes: 2 additions & 5 deletions src/Providers/ToolkitServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
use Simtabi\Laranail\Toolkit\Services\ModelService;
use Simtabi\Laranail\Toolkit\Services\RouteService;
use Simtabi\Laranail\Toolkit\Macros\MacroableModels;
use Simtabi\Laranail\Toolkit\Services\SettingsStore;
use Simtabi\Laranail\Toolkit\Services\SystemService;
use Simtabi\Laranail\Toolkit\Services\SessionService;
use Simtabi\Laranail\Toolkit\Traits\ApiResponseTrait;
Expand Down Expand Up @@ -51,7 +50,6 @@
use Simtabi\Laranail\Toolkit\Http\Middleware\EmailObfuscatorMiddleware;
use Simtabi\Laranail\Toolkit\Modules\Eventing\Listeners\LogCacheEvents;
use Simtabi\Laranail\Toolkit\Services\Contracts\LoggerServiceInterface;
use Simtabi\Laranail\Toolkit\Services\Contracts\SettingsStoreInterface;
use Simtabi\Laranail\Toolkit\Services\Contracts\SystemServiceInterface;
use Simtabi\Laranail\Toolkit\Services\Contracts\SessionServiceInterface;
use Simtabi\Laranail\Toolkit\Services\Contracts\CacheRepositoryInterface;
Expand Down Expand Up @@ -270,8 +268,7 @@ private function registerBindings(): void
$this->app->bind(CacheRepositoryInterface::class, CacheService::class);
$this->app->bind(LoggerServiceInterface::class, LogService::class);

// Settings store, rate limiter and scheduler service contracts.
$this->app->bind(SettingsStoreInterface::class, SettingsStore::class);
// Rate limiter and scheduler service contracts.
$this->app->bind(RateLimiterServiceInterface::class, RateLimiterService::class);
$this->app->bind(SchedulerServiceInterface::class, SchedulerService::class);

Expand All @@ -290,7 +287,7 @@ private function registerBindings(): void
// `app(...)` keeps resolving them.
$this->loadClass(ApiResponseTrait::class);
$this->loadClass(FileProcessingTrait::class);
$this->loadServiceClasses([SettingsStore::class, SchedulerService::class, LogService::class]);
$this->loadServiceClasses([SchedulerService::class, LogService::class]);
$this->loadRateLimiterService();
$this->loadCacheService();
}
Expand Down
45 changes: 0 additions & 45 deletions src/Services/Contracts/SettingsStoreInterface.php

This file was deleted.

115 changes: 0 additions & 115 deletions src/Services/SettingsStore.php

This file was deleted.

9 changes: 0 additions & 9 deletions src/ToolkitManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
use Simtabi\Laranail\Toolkit\Modules\Archiver\ArchiverServiceInterface;
use Simtabi\Laranail\Toolkit\Modules\Livewire\LivewireServiceInterface;
use Simtabi\Laranail\Toolkit\Services\Contracts\LoggerServiceInterface;
use Simtabi\Laranail\Toolkit\Services\Contracts\SettingsStoreInterface;
use Simtabi\Laranail\Toolkit\Services\Contracts\SystemServiceInterface;
use Simtabi\Laranail\Toolkit\Services\Contracts\SessionServiceInterface;
use Simtabi\Laranail\Toolkit\Services\Contracts\CacheRepositoryInterface;
Expand Down Expand Up @@ -228,14 +227,6 @@ public function log(): LoggerServiceInterface
return $this->app->make(LoggerServiceInterface::class);
}

/**
* Runtime settings store (dynamic, persisted-at-runtime key/value JSON).
*/
public function settings(): SettingsStoreInterface
{
return $this->app->make(SettingsStoreInterface::class);
}

/**
* Named-profile rate limiter (attempts/decay over the cache store).
*/
Expand Down
Loading
Loading