ifabula/sevola-interceptor-helper

Laravel database interceptor for automatic field encryption/decryption using Sevola SDK

Maintainers

Package info

gitlab.com/kasfi.tamiya/sevola-php-interceptor-helper

Issues

pkg:composer/ifabula/sevola-interceptor-helper

Statistics

Installs: 11

Dependents: 0

Suggesters: 0

Stars: 0

v1.0.4 2026-05-14 19:40 UTC

This package is not auto-updated.

Last update: 2026-05-14 12:45:20 UTC


README

Zero-integration encryption/decryption for Laravel applications powered by the Sevola SDK.

Configure once in Sevola CMS, install this package, and every Eloquent model automatically honours the encryption rulesโ€”no traits, no code changes.

Latest Version License

Table of Contents

Why the Helper Exists

Enterprises often need to encrypt Personally Identifiable Information (PII) without rewriting existing Laravel codebases. The Sevola PHP Interceptor Helper fetches field-level encryption rules from the Sevola Central Dashboard API, transparently encrypts data before it is written, and decrypts it again when readโ€”so developers keep using Eloquent exactly as before.

Key Features

  • ๐Ÿ” True zero-integration โ€“ encryption happens automatically for every Eloquent model; no traits or manual hooks required.
  • ๐Ÿง  Configuration-driven โ€“ encryption rules live in Sevola CMS, fetched securely via the Central Dashboard API.
  • โšก Global interception โ€“ the service provider attaches framework-level listeners to saving and retrieved events.
  • ๐ŸŽฏ Column-level control โ€“ pick exactly which columns are encrypted, per-table, per-database.
  • ๐Ÿงฎ Algorithm aware โ€“ supports FF1 format-preserving encryption and AES transit encryption.
  • ๐Ÿ”’ Encrypted API transport โ€“ all communication with the Central Dashboard uses AES-256-GCM + HMAC-SHA256; no config is ever sent or received in plaintext.
  • ๐Ÿ—„๏ธ Two-layer caching โ€“ encryption config (from the dashboard) and FF1 keys (from the Sevola API) are both cached, keeping response times fast even for large result sets.
  • ๐Ÿชต Rich logging โ€“ optional structured logging for auditing and debugging.
  • ๐Ÿ› ๏ธ Manual APIs still available โ€“ access ConfigService, EncryptionService, and ModelEncryptionManager for one-off jobs or raw queries.
  • ๐ŸŽš๏ธ Per-request ciphertext toggle โ€“ opt in to encrypted responses using SevolaContext.

Requirements

ComponentMinimum
PHP8.2
Laravel11.x (works with L10 via manual provider registration)
Sevola SDKifabula/sevola-sdk-php (installed automatically)
Central DashboardSevola Central Management API reachable from your server

Installation

  1. Require the package

    composer require ifabula/sevola-interceptor-helper
    
  2. (Optional) Publish the configuration file

    php artisan vendor:publish --tag=sevola-config
    

    This creates config/sevola.php. Publishing is recommended when you need to customise defaults (cache TTL, log channel, etc.).

  3. Laravel service provider

    • Laravel 11+: auto-discovery registers the provider automatically.
    • Laravel โ‰ค 10: add Ifabula\SevolaInterceptor\SevolaServiceProvider::class to the providers array in config/app.php.

Configuring the Helper

Environment variables

Add these entries to .env (or your secrets manager):

# โ”€โ”€ Required โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

# Sevola API โ€“ used for FF1 / AES encryption operations
SEVOLA_API_KEY=your-api-key
SEVOLA_BASE_URL=https://your-sevola-api-url/

# Central Dashboard โ€“ encryption config is fetched from here
CENTRAL_DASHBOARD_URL=https://your-central-dashboard-url/

# Shared AES-256 key for dashboard API transport (64 hex chars = 32 bytes)
# Must match DEALER_ENCRYPTION_SALT on the Central Dashboard server
DEALER_ENCRYPTION_SALT=your-64-char-hex-string

# โ”€โ”€ Optional โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

# How long to cache the encryption config fetched from the dashboard (seconds)
SEVOLA_CACHE_TTL=300

# Cache the FF1/REST key from the Sevola API (strongly recommended for large result sets)
SEVOLA_ENABLE_SDK_CACHE=true
SEVOLA_SDK_CACHE_TTL=300

# Logging
SEVOLA_LOGGING=false
SEVOLA_LOG_CHANNEL=stack
SEVOLA_DEBUG=false

# Experimental raw-query interceptor (disabled by default; Eloquent listeners are sufficient)
SEVOLA_ENABLE_QUERY_LISTENER=false

# Feature control โ€“ which interceptor directions are active (default: none / dormant)
SEVOLA_INTERCEPTOR_RUNNING_FEATURES=encrypt,decrypt

SEVOLA_ENABLE_SDK_CACHE=true is strongly recommended for production. Without it, every column decryption makes a separate HTTP call to the Sevola API to fetch the FF1 key. With caching enabled, the key is fetched once and reused for the entire TTL window โ€” making decryption of large result sets orders of magnitude faster.

Sevola CMS configuration

Encryption rules are managed in Sevola CMS. For each table you want to protect:

  1. Open Encryption Config inside Sevola CMS.
  2. Create an entry specifying the database, table, columns to encrypt, and the algorithm.
  3. Set the entry status to ACTIVE.

The helper fetches this config from the Central Dashboard API on demand (cached). Once active, every Eloquent query touching that table automatically encrypts/decrypts the listed columns.

No code changes are needed in the Laravel project. As soon as the config is active and the helper is installed, the model data is protected.

Quick Start Checklist

  1. โœ… composer require ifabula/sevola-interceptor-helper
  2. โœ… Add the four required env vars (SEVOLA_API_KEY, SEVOLA_BASE_URL, CENTRAL_DASHBOARD_URL, DEALER_ENCRYPTION_SALT).
  3. โœ… Set SEVOLA_ENABLE_SDK_CACHE=true for production workloads.
  4. โœ… Ensure the Sevola CMS entry exists for each table (status = ACTIVE).
  5. โœ… (Laravel โ‰ค 10) Register the service provider manually.
  6. โœ… Set SEVOLA_INTERCEPTOR_RUNNING_FEATURES=encrypt,decrypt to activate both directions (or encrypt / decrypt alone for partial mode).
  7. โ–ถ๏ธ Use your Eloquent models exactly as before โ€” encrypted columns are handled automatically.

To verify quickly, enable logging (SEVOLA_LOGGING=true, SEVOLA_DEBUG=true) and inspect storage/logs/laravel.log. You should see [Sevola] entries confirming encryption/decryption activity for configured tables.

How the Helper Works

  1. Bootstrapping โ€“ SevolaServiceProvider registers services and attaches listeners to global Eloquent events.
  2. Config fetch โ€“ when a model is first accessed, ConfigService calls the Central Dashboard API (POST /dealer/encryption-config) with an AES-256-GCM encrypted + HMAC-signed payload. The response (also encrypted) is verified, decrypted, and cached.
  3. On Save โ€“ Model::saving fires; the helper encrypts dirty columns listed in the config and writes the ciphertext back onto the model before the INSERT/UPDATE.
  4. On Retrieve โ€“ Model::retrieved fires; the helper decrypts the relevant attributes and calls syncOriginal() so Laravel treats the decrypted values as the original state.
  5. Key caching โ€“ the FF1 key fetched from the Sevola API is cached in memory for the SDK cache TTL, so large result sets (hundreds of rows) only pay one key-fetch round-trip.

The helper does nothing for tables that have no active CMS config โ€” safe to deploy broadly without code toggles.

Available Services

ServiceClassResponsibilities
ConfigurationIfabula\SevolaInterceptor\Services\ConfigServiceFetch and cache encryption config from the Central Dashboard.
EncryptionIfabula\SevolaInterceptor\Services\EncryptionServiceEncrypt/decrypt associative arrays via the Sevola SDK.
Model ManagerIfabula\SevolaInterceptor\Services\ModelEncryptionManagerCore logic for Eloquent lifecycle event handling.
Query Interceptor (experimental)Ifabula\SevolaInterceptor\Interceptors\QueryInterceptorLow-level listener for raw query events. Disabled by default.

All services are container singletons โ€” resolve with app(ConfigService::class), etc.

Usage Examples

1. Plain Eloquent usage (no code changes)

$user = App\Models\User::create([
    'name'  => 'Jane Doe',
    'email' => 'jane@example.com',  // stored encrypted in DB
    'phone' => '555-1234',          // stored encrypted in DB
]);

$user = App\Models\User::find($user->id);
$user->email; // "jane@example.com"  (decrypted automatically)
$user->phone; // "555-1234"

2. Manual encryption/decryption for raw arrays

use Ifabula\SevolaInterceptor\Services\ConfigService;
use Ifabula\SevolaInterceptor\Services\EncryptionService;

$config = app(ConfigService::class)->getConfig('my_database', 'users');

if ($config?->isActive()) {
    $payload   = ['email' => 'john@example.com', 'phone' => '555-9999'];
    $encrypted = app(EncryptionService::class)->encryptData($payload, $config);
    $decrypted = app(EncryptionService::class)->decryptData($encrypted, $config);
}

3. Clearing configuration cache

app(ConfigService::class)->clearCache();                     // all tables
app(ConfigService::class)->clearCache('my_database', 'users'); // specific table

4. Returning ciphertext for a specific query

use Ifabula\SevolaInterceptor\Support\SevolaContext;

// Default: decrypted
$records = MyModel::all();

// Encrypted values for this call only
$encrypted = SevolaContext::withReturnEncrypted(fn () => MyModel::all());

// Manual push/pop
SevolaContext::pushReturnEncrypted();
try {
    $cipherRecords = MyModel::all();
} finally {
    SevolaContext::pop();
}

Advanced Topics

Logging & Observability

  • SEVOLA_LOGGING=true enables informational logs (provider loaded, dashboard requests, etc.).
  • SEVOLA_DEBUG=true adds granular debug logs (cache hits, attribute lists, payloads).
  • Use SEVOLA_LOG_CHANNEL to route logs to any Laravel channel (daily file, Slack, etc.).

Cache Strategy

  • Config cache (SEVOLA_CACHE_TTL) โ€” caches the column list fetched from the Central Dashboard per (database, table) pair. Call ConfigService::clearCache() after changing CMS entries to invalidate immediately.
  • SDK key cache (SEVOLA_ENABLE_SDK_CACHE, SEVOLA_SDK_CACHE_TTL) โ€” caches the FF1/REST key from the Sevola API. Without this, every column decryption makes a separate HTTP round-trip. Always enable in production.

Query Listener (experimental)

Flip SEVOLA_ENABLE_QUERY_LISTENER=true to activate QueryInterceptor. Intended for low-level query event hooks; the global Eloquent listeners are sufficient for most use cases.

Working with Query Builder / Raw SQL

Eloquent models auto-decrypt attributes. For direct DB::select() calls, decrypt arrays manually via EncryptionService. Bulk CSV imports can pre-encrypt using the same service before calling DB::table()->insert().

Troubleshooting

SymptomPossible CauseFix
No encryption or decryption at allSEVOLA_INTERCEPTOR_RUNNING_FEATURES not setSet to encrypt,decrypt (or the desired subset); default is dormant
Values remain encrypted on retrieveCMS entry missing or INACTIVESet status to ACTIVE in Sevola CMS; clear config cache
No encryption on saveCMS entry missing; listeners not runningEnable debug logging; ensure provider is registered
SEVOLA_API_KEY is not configured.env missing keyAdd key; run php artisan config:clear
CENTRAL_DASHBOARD_URL is not configured.env missing keyAdd CENTRAL_DASHBOARD_URL
DEALER_ENCRYPTION_SALT is not configured.env missing keyAdd 64-char hex salt matching the dashboard server
Response signature verification failedSalt mismatch between app and dashboardVerify DEALER_ENCRYPTION_SALT matches the server value
Decryption failed: ERROR: Request failedSevola API unreachableVerify SEVOLA_BASE_URL and network connectivity
Slow responses on large result setsSDK key cache disabledSet SEVOLA_ENABLE_SDK_CACHE=true
Stale config after CMS changeConfig still cachedCall app(ConfigService::class)->clearCache()

Enable debug logging and watch storage/logs/laravel.log to diagnose issues. You will see entries such as:

[Sevola] Fetching config from central dashboard {"database":"my_db","table":"users"}
[Sevola] Config loaded from central dashboard {"columns":["email","phone"]}
[Sevola] Decrypting attributes during retrieved {"model":"App\\Models\\User"}

FAQ

Do I need to modify my Eloquent models?

No. The helper intercepts Eloquent lifecycle events globally. Keep your models exactly as they are.

How do I disable encryption temporarily?

Mark the CMS entry as INACTIVE and clear the helper cache. Existing ciphertext stays encrypted in the database.

Can I encrypt new tables without deploying code?

Yes. Add the table to Sevola CMS, set it ACTIVE, and the helper picks it up on the next cache miss.

What about queue workers or scheduled jobs?

As long as the job boots Laravel normally, the service provider runs and encryption stays active.

Does this helper change database schemas?

No. The helper only transforms values going into/out of the database. Schema migrations are unchanged.

Why is DEALER_ENCRYPTION_SALT needed?

All requests to the Central Dashboard are encrypted with AES-256-GCM and signed with HMAC-SHA256 using this salt. It must match the value configured on the Central Dashboard server. This ensures no encryption config is ever transmitted in plaintext.

Contributing & Support

Issues and feature requests are welcome on GitLab. For commercial support, please contact Ifabula directly.

Made with โค๏ธ by Ifabula.