Search by

froomle / sdk

froomle_engineering

Server-side Froomle OAuth and Items API primitives

0.1.0 2026-08-12 14:24 UTC

This package is auto-updated.

Last update: 2026-10-27 13:37:48 UTC


README

froomle/sdk provides reusable server-side primitives for integrating PHP applications with Froomle. Drupal modules, WordPress plugins and custom PHP applications can share this package without inheriting CMS-specific behavior.

The current 0.1.x line provides:

  • OAuth 2.0 client-credentials token acquisition for isolated Items and Recommendations connection profiles;
  • opaque token caching, refresh skew and injectable cache/lock adapters;
  • Items API create, upsert, enable, disable and delete operations;
  • PSR-18 HTTP, PSR-17 request/stream and PSR-3 logging integration;
  • one forced OAuth refresh after an Items API 401;
  • bounded binary exponential backoff for transport failures, 429 and 5xx;
  • typed results and actionable exception classes.

This is a server-only package. It does not render recommendations, parse or rewrite HTML, buffer application output, set cookies, inject scripts, decode JWT claims or contain Drupal/WordPress-specific integration code.

Requirements

  • PHP 8.1 or newer
  • ext-mbstring
  • a PSR-18 HTTP client
  • PSR-17 request and stream factories

The package deliberately does not force a particular HTTP implementation. Framework integrations should inject the HTTP stack they already use.

Installation

composer require froomle/sdk:^0.1

The 0.1.x API replaces the legacy 0.0.x page-rewriting SDK. Historical 0.0.x releases remain available, but they are not part of this server SDK.

Items API

Create one Items connection profile and inject your PSR implementations:

<?php

use Froomle\Sdk\ClientFactory;
use Froomle\Sdk\ConnectionProfile;

$factory = new ClientFactory($httpClient, $requestFactory, $streamFactory);
$profile = new ConnectionProfile(
    'customer-tenant',
    ConnectionProfile::ITEMS,
    $itemsClientId,
    $itemsClientSecret,
);

$items = $factory->items($profile, 'customer-production', 'article');

$result = $items->upsert('article-42', [
    'title' => 'Example article',
    'tags' => ['news', 'campus'],
    'publication_datetime' => '2026-08-12T12:00:00+02:00',
]);

if ($result->statusCode() === 200) {
    // The Items API accepted the update.
}

Available operations:

$items->create($payload);
$items->upsert($itemId, $payload);
$items->enable($itemId);
$items->disable($itemId);
$items->delete($itemId);

Every HTTP 2xx response is final success from the client's perspective. The SDK does not inspect Froomle's downstream processing after the API has accepted the request.

OAuth profiles

Items and Recommendations credentials must use separate profiles, even when they belong to the same tenant:

$itemsProfile = new ConnectionProfile(
    'customer-tenant',
    ConnectionProfile::ITEMS,
    $itemsClientId,
    $itemsClientSecret,
);

$recommendationsProfile = new ConnectionProfile(
    'customer-tenant',
    ConnectionProfile::RECOMMENDATIONS,
    $recommendationsClientId,
    $recommendationsClientSecret,
);

$recommendationsTokens = $factory->tokenProvider($recommendationsProfile);
$bearer = $recommendationsTokens->getToken()->value();

The SDK sends only grant_type, client_id and client_secret to the token endpoint. Tokens are opaque and cache identities keep Items and Recommendations profiles isolated.

Never log or serialize ConnectionProfile::clientSecret() or AccessToken::value(). Object debug output redacts both values.

Token persistence and locking

InMemoryTokenStore and InProcessRefreshLock are safe defaults for a simple PHP process. Long-running or multi-worker applications should provide durable implementations of:

  • Froomle\Sdk\OAuth\TokenStoreInterface;
  • Froomle\Sdk\OAuth\RefreshLockInterface.

Drupal, WordPress and other frameworks should adapt their native cache and lock services to these interfaces. Credentials and bearer tokens must remain server-side.

Failures and retries

All SDK exceptions extend Froomle\Sdk\Exception\FroomleException:

  • AuthenticationException: OAuth credentials or a refreshed token were rejected;
  • ClientRequestException: the Items API returned a final non-401 4xx;
  • RetryableException: 429 or 5xx responses exhausted the retry budget;
  • TransportException: transport failures exhausted the retry budget;
  • ProtocolException: a response or generated contract was invalid.

ClientRequestException and RetryableException expose statusCode(). Retries are bounded and use jittered binary exponential backoff. Applications can inject a custom RetryPolicy, sleeper and logger through ClientFactory.

Development and release provenance

The package is generated from the shared Froomle SDK source and conformance fixtures. Its generated protocol runtime is an internal implementation detail; public integrations should use only Froomle\Sdk\** APIs documented above.

Every distribution contains FROOMLE-PROVENANCE.json, which records the exact source commit and payload digest. Releases are assembled from a strict whitelist and verified through a clean Composer consumer before publication.

See CHANGELOG.md for PHP package release notes.

License

froomle/sdk is licensed under the Apache License 2.0. The complete license text is included in every Composer distribution; see LICENSE.