Topics: Credential Providers and Consumers¶
A Topic is a named capability contract. It bridges what an application needs and what a credential provides, making it possible for MultiFlexi to automatically match applications with the right credentials at both configuration time and runtime.
The Two Sides of a Topic¶
- Provider
A credential (instantiated from a CredentialProtoType) declares that it provides one or more topics. For example, a credential based on the
FioBankprototype provides topicFioBank.- Consumer
An application declares the topics it requires in the
requirementssection of itsapp.jsondefinition. A RunTemplate cannot start a job until every required topic is satisfied by an assigned credential.
Example — bank statement downloader:
{
"requirements": ["FioBank"]
}
When a RunTemplate is configured, the administrator assigns a FioBank credential
to satisfy the FioBank requirement. The UI shows an error if no suitable
credential type is defined for the company, or a warning if no credential is yet
assigned.
Two-Phase Resolution¶
Topic resolution happens in two phases at different points in the job lifecycle.
Phase 1 — Static Binding (Configuration Time)¶
Does a credential of a type that provides the topic exist, and is it assigned to the RunTemplate?
This is a binary check performed in the web UI when the administrator configures a RunTemplate:
Provider not installed → the requirement card shows red (
danger). The required extension package must be installed.Provider installed, no credential type defined → the card shows orange (
warning). A credential type must be created for the company first.Credential type exists, no credential assigned → the card shows a dropdown for the administrator to choose or create a credential.
Credential assigned → the card shows green (
success) and the current live availability badge (see Phase 2).
Phase 2 — Dynamic Verification (Job Runtime)¶
Is the backing service actually reachable and the credential valid right now?
Immediately before starting a job, the executor calls checkAvailability() on
every assigned credential’s prototype. The result determines whether the job runs:
State |
Job outcome |
Meaning |
|---|---|---|
|
Runs |
Service live, credential valid |
|
Runs |
No check implemented — backward compatible, never blocks |
|
Deferred |
Service reachable but impaired (e.g. server busy or under load) |
|
Deferred |
Transient failure: timeout, connection refused, 5xx response |
|
Blocked (no retry) |
Permanent fault: bad token, unreadable certificate, missing field |
Deferred jobs are re-queued after the check’s TTL (seconds) expires.
misconfigured jobs are never retried — administrator action is required.
All non-available / non-unknown results are reported to the SQL log,
Zabbix (when ZABBIX_SERVER is set), and OpenTelemetry (when OTEL_ENABLED
is set). Blocked jobs appear in the job list with exit code 75 (POSIX
EX_TEMPFAIL) and an orange job-credential-blocked row class.
Relationship Diagram¶
app.json
┌────────────────────────────┐
│ "requirements": ["FioBank"]│ ← consumer declares needed topic
└───────────────┬────────────┘
│ Phase 1 (config time)
▼
┌─────────────────────────────────┐
│ RunTemplate ─── Credential │ ← administrator assigns provider
│ (assigned at configuration) │
└───────────────┬─────────────────┘
│ Phase 2 (runtime, per-job)
▼
┌──────────────────────────────────────────┐
│ CredentialProtoType.checkAvailability() │
│ returns CredentialCheckResult │
└──────────┬───────────────────────────────┘
│
┌──────────▼──────────────────────────────────────┐
│ isSatisfied()? │
│ true (available / unknown) → run job │
│ false (degraded / unavailable) → defer + retry │
│ false (misconfigured) → block, notify │
└──────────────────────────────────────────────────┘
Web UI Indicators¶
- RunTemplate configuration page
Each requirement card shows a live availability badge after the credential dropdown:
✅
available— green⚠️
degraded— orange🔴
unavailable— red🚫
misconfigured— redℹ️
unknown— blue (no check implemented)
- Credential configuration form
When no custom UI helper exists for the credential type, the form renders a universal availability panel (alert + optional details list) after the field inputs. Credential types with a dedicated UI helper (e.g. mServer) render their own availability section instead.
- Job list
Jobs blocked by a failed credential check appear with exit code
75and an orange row background (job-credential-blocked).
Implementing a Topic Provider¶
A credential prototype becomes a topic provider by:
Its PHP class name (e.g.
MultiFlexi\CredentialProtoType\FioBank) matching the topic name (e.g.FioBank) inapp.json.Optionally implementing
checkAvailability()for Phase 2 live checks:
namespace MultiFlexi\CredentialProtoType;
class FioBank extends \MultiFlexi\CredentialProtoType
implements \MultiFlexi\credentialTypeInterface,
\MultiFlexi\checkableCredentialInterface
{
#[\Override]
public function checkAvailability(): \MultiFlexi\CredentialCheckResult
{
$token = (string) ($this->configFieldsInternal
->getFieldByCode('FIO_TOKEN')?->getValue() ?? '');
if ($token === '') {
return new \MultiFlexi\CredentialCheckResult(
\MultiFlexi\CredentialState::Misconfigured,
_('FIO_TOKEN is not set'),
time(),
);
}
// Host-reachability only — avoids 30 s rate limit and cursor side effect.
$ch = curl_init('https://fioapi.fio.cz/');
curl_setopt_array($ch, [\CURLOPT_NOBODY => true, \CURLOPT_CONNECTTIMEOUT => 5, \CURLOPT_TIMEOUT => 5]);
curl_exec($ch);
$errno = curl_errno($ch);
return $errno === 0
? new \MultiFlexi\CredentialCheckResult(\MultiFlexi\CredentialState::Available, '', time(), 300)
: new \MultiFlexi\CredentialCheckResult(\MultiFlexi\CredentialState::Unavailable,
sprintf(_('Fio API unreachable: %s'), curl_strerror($errno)), time(), 60);
}
}
The base class \MultiFlexi\CredentialProtoType provides a default no-op
implementation that returns Unknown — so prototypes without a live check never
block jobs, ensuring backward compatibility.
See Also¶
MultiFlexi Credential Management System — three-tier credential architecture
credential-prototype in the development section — implementing credential prototypes
Credential Availability Checks — check states and built-in implementations
Job Lifecycle — how job states relate to topic satisfaction