Platform Services

This page covers the source-defined cache, encryption, validation, and HTTP security services in imspr/system. Their declarations and defaults describe implementation behavior, not deployment configuration, caller reachability, effective HTTP policy, or successful runtime execution.

[!WARNING]

  • Cache fallback: CacheFactory::getHandler can select the dummy adapter when configured handlers are unsupported or initialization raises CriticalError; the source does not guarantee a functioning persistent cache.
  • Cache path safety: FileHandler places the supplied key directly into filesystem paths. The inspected implementation shows no key allowlist, sanitization, or containment check, so callers must not treat it as a path-isolation boundary.
  • Encryption secret: imspr/app/Config/Encryption.php contains a hard-coded starter-key default. Its presence is not evidence of a safe deployment secret; deployment configuration must override it through an appropriate secret boundary.
  • CSP enforcement: ContentSecurityPolicy constructs headers and nonce substitutions in source, but no inspected caller proves that finalization runs for deployed responses. The configured policy is therefore not evidence of effective HTTP security enforcement.
  • Deployment boundary: The inspected paths establish declarations and source-defined control flow only. They do not establish deployment assembly, registration, runtime reachability, or successful execution.

Service lookup

[
    {
        "title": "Cache selection and file storage",
        "body": "**CacheFactory::getHandler** validates that the configuration provides a handler map, a primary handler, and a backup handler. Explicit handler names take precedence; otherwise it uses the configured names. Both names must exist in the valid-handler map before instantiation.\n\nThe source then instantiates the primary adapter and checks **isSupported**. If support fails, it instantiates the backup and checks it as well. If both support checks fail, it creates the dummy handler. After selecting an adapter, it calls **initialize**. A `CriticalError` causes a retry through the backup path, with the dummy handler supplied as the final fallback. The method returns the selected adapter.\n\n`imspr/app/Config/Cache.php` declares `file` as the primary handler, `dummy` as the backup handler, and `WRITEPATH . 'cache/'` as the default store path. These are source defaults only.\n\n**CacheInterface** exposes **isSupported(): bool** as the support contract.\n\n**FileHandler** uses the configured store path or a `WRITEPATH . 'cache'` fallback, normalizes the directory path with a trailing separator, and stores the configured prefix. Its constructor raises a cache exception when the path is not writable. **isSupported** reports `is_writable($this->path)`.\n\n**save(string $key, $value, int $ttl = 60)** prefixes the key and serializes the write time, TTL, and value into the cache file. **writeFile** performs the file write with an exclusive lock. A successful write changes the file mode to `0640` and returns `true`; an unsuccessful write returns `false`.\n\n**getItem** returns `false` when the cache file is absent. For an existing file it unserializes the stored record, removes the file when a positive TTL has expired, and otherwise returns the stored record. File reads, writes, metadata access, and deletion build their target by concatenating the configured directory with the prefixed string key."
    },
    {
        "title": "Encryption contract and initialization",
        "body": "**EncrypterInterface** defines **encrypt($data, $params = null)** for converting plaintext to ciphertext and **decrypt($data, $params = null)** for converting encrypted data to plaintext. The optional parameter value can override encryption parameters such as the key.\n\n**Encryption::initialize** optionally takes a `BaseConfig` and uses its driver and key values. It requires a driver, rejects drivers outside its supported-driver list, and requires a non-empty key. The inspected supported-driver list contains only `OpenSSL`.\n\nInitialization derives an HMAC key with `hash_hkdf` using the configured `SHA512` digest, constructs the selected handler dynamically, and returns the handler. **Encryption::createKey($length = 32)** returns `random_bytes($length)` for key generation.\n\n`imspr/app/Config/Encryption.php` declares `OpenSSL` and a non-empty starter-key default. Do not interpret that source default as a deployment secret; the security consequence and required override boundary are stated above."
    },
    {
        "title": "Content Security Policy construction",
        "body": "**ContentSecurityPolicy::finalize** processes the response body with **generateNonces** before calling **buildHeaders**.\n\nWhen the response body is empty, **generateNonces** returns without changing it. Otherwise, it replaces `{csp-script-nonce}` and the corresponding style nonce placeholder with random 12-byte hexadecimal nonces, adds matching nonce sources, and writes the transformed body back to the response.\n\n**buildHeaders** maps configuration properties to CSP directive names, including `base-uri`, `child-src`, `connect-src`, `default-src`, `font-src`, `form-action`, `frame-ancestors`, `img-src`, `media-src`, `object-src`, `plugin-types`, `script-src`, `style-src`, `manifest-src`, `sandbox`, and `report-uri`. Empty `baseURI` and `defaultSrc` values become `self`.\n\nOrdinary sources populate the `Content-Security-Policy` header, while sources classified as report-only populate `Content-Security-Policy-Report-Only`. The per-source classification can be set explicitly or inherit **reportOnly**; **buildHeaders** appends each non-empty header collection independently, so both headers can be present. It adds `upgrade-insecure-requests` only when that option is enabled.\n\n`imspr/app/Config/ContentSecurityPolicy.php` declares report-only mode and `upgradeInsecureRequests` as `false`, with `self` defaults for script, style, and image sources. The configuration leaves `defaultSrc` and several other directive properties null. **buildHeaders** defaults only empty `baseURI` and `defaultSrc` to `self`; other null properties remain unset and are skipped unless populated before header construction. These declarations do not prove that the finalization lifecycle is connected to deployed responses."
    },
    {
        "title": "Validation rules",
        "body": "**Rules::required** returns `true` for objects, non-empty arrays, and strings whose trimmed value is not empty. It returns `false` for the corresponding empty cases.\n\n**Rules::in_list** splits a comma-separated list, trims each entry, and compares the supplied value with `in_array(..., true)`. The comparison is strict.\n\n**Rules::is_unique** parses a `table.field` specification and optional ignored-field and ignored-value components. It connects through the selected database group, selects one matching row, filters by the supplied field value, and limits the query to one result. When both ignore components are present, it excludes the ignored value. It returns `true` only when the query finds no row."
    }
]

Updated