This document is the authoritative list of every interface element from this repository that is consumed or depended upon by other Starisian platform repositories (Helios, Dheghom, Sky, Mehns, Ouroboros, and site-level plugins).
Keep this file current. If you add a public constant, filter, hook, REST endpoint, or class, register it here.
All six methods are frozen. Their signatures MUST NOT change. These are the only public interface from the old sparxstar-user-environment-check plugin and are consumed by every site-level plugin, theme, and integration that referenced UEC.
namespace Starisian\SparxstarUEC;
StarUserEnv::get_browser_name(): string
StarUserEnv::get_os(): string
StarUserEnv::get_device_type(): string
StarUserEnv::get_network_effective_type(): string
StarUserEnv::get_ip_address(): string
StarUserEnv::get_location(): arraynamespace Starisian\Sparxstar\Sirus\core;
ContextEngine::current(): SirusContext // Throws ContextBootException on failure. Never null.
ContextEngine::buildFromDevice(DeviceRecord $device): SirusContext
ContextEngine::build(): SirusContextContract:
current()is the primary accessor. All downstream code calls this.- Throws
ContextBootException(never returns null, never returns partial). - CLI SAPI path: returns fixed system context (
SYSTEM/GLOBAL/CLI). - Caches via
ContextCachefor the duration of the request.
namespace Starisian\Sparxstar\Sirus\core;
// Constructor (all readonly):
new SirusContext(
string $context_id,
string $environment_id,
string $network_id,
string $site_id,
string $device_id,
string $session_id,
?string $identity_id,
?string $authority_id,
array $role_set,
array $capabilities,
string $trust_level,
float $trust_score, // [0.0, 1.0] — from TrustEngine / TrustResolver
int $issued_at,
int $expires,
)
// Portable payload (for cross-domain handoff):
SirusContext::toPortablePayload(): array // Keys: ctx, env, net, site, dev, auth, caps, tl, ts, iat, expPortable payload field map:
| Key | Property | Type |
|---|---|---|
ctx |
context_id |
string |
env |
environment_id |
string |
net |
network_id |
string |
site |
site_id |
string |
dev |
device_id |
string |
auth |
authority_id |
string|null |
caps |
capabilities |
string[] |
tl |
trust_level |
string |
ts |
trust_score |
float (4 d.p.) |
iat |
issued_at |
int (Unix) |
exp |
expires |
int (Unix) |
Note:
identity_idis NOT included in the portable payload. It must be resolved independently by each receiving service.
namespace Starisian\Sparxstar\Sirus\core;
TrustEngine::compute(array $signals): array // returns {trust_score: float, trust_level: string}
TrustEngine::scoreToLevel(float $score): stringFrozen algorithm (MUST NOT change without spec update):
| Signal key | Deduction |
|---|---|
device_drifting (bool) |
−0.3 |
geo_mismatch (bool) |
−0.2 |
new_session (bool) |
−0.1 |
recent_failures (bool) |
−0.3 |
Base = 1.0. Result clamped to [0.0, 1.0].
Level mapping (frozen):
| Score | Level |
|---|---|
| ≥ 0.7 | NORMAL |
| > 0.0 | ELEVATED |
| = 0.0 | CRITICAL |
Public constants (consumed by TrustResolver):
TrustEngine::DEDUCTION_DEVICE_DRIFTING // 0.3
TrustEngine::DEDUCTION_GEO_MISMATCH // 0.2
TrustEngine::DEDUCTION_NEW_SESSION // 0.1
TrustEngine::DEDUCTION_RECENT_FAILURES // 0.3
TrustEngine::LEVEL_NORMAL // 'NORMAL'
TrustEngine::LEVEL_ELEVATED // 'ELEVATED'
TrustEngine::LEVEL_CRITICAL // 'CRITICAL'namespace Starisian\Sparxstar\Sirus\core;
TrustResolver::evaluate(DeviceRecord $device): float // [0.0, 1.0]Derives trust score from DeviceRecord::$trust_level as a base, then applies TrustEngine deductions for drift and new sessions. Used exclusively by ContextEngine::buildFromDevice().
Credential base scores (frozen):
| Level | Base |
|---|---|
elder |
0.95 |
contributor |
0.90 |
user |
0.85 |
device |
0.70 |
anonymous / other |
0.50 |
namespace Starisian\Sparxstar\Sirus\core;
PulseGenerator::generate(SirusContext $context, int $now = 0, int $ttlSeconds = PulseGenerator::PULSE_TTL): ContextPulse
PulseGenerator::resolveTtl(ResourceSensitivity $sensitivity): intRequirements:
- PHP constant
SPARXSTAR_PULSE_SIGNING_KEYmust be defined and ≥ 32 bytes. Throws\RuntimeExceptionotherwise. - Signing algorithm: HMAC-SHA256.
ContextPulseNEVER containsidentity_id.$now = 0means usetime(). Pass an explicit timestamp for deterministic testing.$ttlSecondsdefaults toPULSE_TTL(60). Callers that want the spec's sensitivity-driven TTL strategy should resolve a value viaresolveTtl(ResourceSensitivity $sensitivity)first and pass it through — see thesparxstar_sirus_pulse_ttl_secondsfilter below.PulseGeneratoritself remains policy-agnostic and does not read TTL from SirusContext.
namespace Starisian\Sparxstar\Sirus\core;
// ResourceSensitivity is a backed int enum: LOW=1, MEDIUM=2, HIGH=3
StepUpPolicy::requiresStepUp(ContextPulse $pulse, ResourceSensitivity $level): bool
StepUpPolicy::getRequiredLevel(ContextPulse $pulse, ResourceSensitivity $level): ?ResourceSensitivity // null = no step-upFrozen policy (spec §15 / Helios §11):
Evaluation order (first match wins):
| Condition | Result |
|---|---|
trust_level === STEP_UP_REQUIRED |
Always requires step-up (pre-flagged context) |
HIGH (3) |
Always requires step-up |
MEDIUM (2) and trust_score < 0.7 |
Requires step-up |
LOW (1) |
Never requires step-up |
Pre-flagged step-up: If a pulse carries trust_level === 'STEP_UP_REQUIRED', step-up is required unconditionally regardless of sensitivity level or numeric trust score. This handles contexts where the issuing system has already detected an anomaly (concurrent sessions, privilege escalation attempt, admin-flagged review).
StepUpPolicy::TRUST_LEVEL_STEP_UP_REQUIRED // 'STEP_UP_REQUIRED'
StepUpPolicy::LEVEL_2_TRUST_THRESHOLD // 0.7StepUpPolicy operates on ContextPulse (not SirusContext) so the same evaluation runs identically at the edge and at the origin. Returns recommendation only. Helios enforces.
ResourceSensitivity enum — src/core/ResourceSensitivity.php:
enum ResourceSensitivity: int {
case LOW = 1;
case MEDIUM = 2;
case HIGH = 3;
}namespace Starisian\Sparxstar\Sirus\core;
// Technical consent (three-level cascade: user meta → site option → STATE_DENIED)
ConsentManager::getTechnicalConsent(int $user_id): string // STATE_GRANTED | STATE_DENIED
ConsentManager::setTechnicalConsent(int $user_id, string $state): bool
// Site authority default (set by site admin)
ConsentManager::getSiteConsentDefault(int $blog_id = 0): string
ConsentManager::setSiteConsentDefault(string $state, int $blog_id = 0): bool
// Purpose-level consent
ConsentManager::getPurposeConsent(int $user_id): array // purpose_key → STATE_*
ConsentManager::setPurposeConsent(int $user_id, string $purpose_key, string $state): bool
// Append-only history
ConsentManager::getHistory(int $user_id): arrayState constants:
ConsentManager::STATE_GRANTED // 'granted'
ConsentManager::STATE_DENIED // 'denied'
ConsentManager::STATE_PENDING // 'pending'Cascade order for getTechnicalConsent():
- Individual user meta (
sirus_technical_consent) — highest priority - Site option (
sirus_technical_consent_default) — authority default - System hard default:
STATE_DENIED— privacy-first
namespace Starisian\Sparxstar\Sirus\core;
// The signing secret is explicit so the class is fully portable — no implicit
// WordPress function calls (no wp_salt(), no wp_json_encode()).
NetworkContextBroker::issueToken(SirusContext $context, string $secret): string // base64url-encoded signed token
NetworkContextBroker::verifyToken(string $token, string $secret): ?SirusContext // null on invalid/expiredSecret: The caller supplies the secret from their environment. In WordPress contexts pass wp_salt('auth'). In edge workers or sovereign deployments use an environment variable. The same secret must be used for both issueToken() and verifyToken(). The class itself never calls wp_salt() or any WordPress function.
Token payload field map: Same as SirusContext::toPortablePayload() above (minus identity_id). ts field added in v1.0 — absent ts is derived from tl for backward compatibility.
Two-stage pipeline — resolution then evaluation:
namespace Starisian\Sparxstar\Sirus\core;
// Stage 1 — Resolution (boundary method): untrusted signals → server-issued DeviceRecord
DeviceContinuity::resolveDevice(
string $device_id,
string $device_secret,
string $fingerprint_hash,
array $environment_data
): DeviceRecord
DeviceContinuity::registerDevice(string $fingerprint_hash, array $environment_data): DeviceRecord
// Stage 2 — Evaluation (analysis method): DeviceRecord → continuity state
DeviceContinuity::evaluateContinuity(DeviceRecord $device): array
// Returns: ['device_hash' => string, 'continuity_score' => float, 'risk_flags' => string[]]Contract:
device_idis ALWAYS server-issued. JS fingerprint is an input toDeviceRecord::fingerprint_hash, not a device identifier.resolveDevice()callsDeviceMatcher::classify()and branches on three outcomes (spec §14.3):- STRONG_MATCH — fingerprint identical; restore device, touch
last_seen. - WEAK_MATCH — verified device, fingerprint changed; restore device, set
trust_level = STEP_UP_REQUIRED(in-memory only), incrementdrift_score. - NO_MATCH — no verified anchor and no matching fingerprint; register new device.
- STRONG_MATCH — fingerprint identical; restore device, touch
evaluateContinuity()throws\RuntimeExceptionif$device->device_idor$device->fingerprint_hashis empty.
Fingerprint scoring and three-way classification (spec §14.3):
namespace Starisian\Sparxstar\Sirus\core;
// Thresholds
DeviceMatcher::STRONG_MATCH_THRESHOLD // 0.8 — restore normally
DeviceMatcher::WEAK_MATCH_THRESHOLD // 0.6 — restore + flag STEP_UP_REQUIRED
// Classification
DeviceMatcher::classify(float $score): MatchResult
// Scoring
DeviceMatcher::scoreHash(string $stored, string $current): float // 1.0 or 0.0
DeviceMatcher::scoreComponents(array $stored, array $current): float // [0.0, 1.0]
// MatchResult cases
MatchResult::STRONG_MATCH // score >= 0.8
MatchResult::WEAK_MATCH // 0.6 <= score < 0.8
MatchResult::NO_MATCH // score < 0.6Component weight keys (snake_case, PHP-authoritative):
canvas_hash (0.30), screen (0.20), timezone (0.15), platform (0.15),
languages (0.10), color_depth (0.05), hardware_concurrency (0.05)
namespace Starisian\Sparxstar\Sirus\core;
IdentityResolver::resolve(): array // Never null. Returns FALLBACK_IDENTITY on Helios failure.Returns: {identity_id: string|null, verification_status: string, authority_memberships: string[], capabilities: string[]}
Machine-readable downstream contract: docs/contracts/sirus-api-contract.v1.json. Seed requests for Helios/Sky/Dheghom smoke wiring: docs/contracts/sirus-api-seed.v1.json.
| Method | Route | Controller | Auth |
|---|---|---|---|
POST |
/wp-json/sirus/v1/event |
SirusEventController |
WP nonce required (X-WP-Nonce or ?_wpnonce) |
GET |
/wp-json/sirus/v1/directives |
SirusDirectiveController |
WP nonce required |
GET |
/wp-json/sirus/v1/directives/{device_id} |
SirusDirectiveController |
WP nonce required |
| Method | Route | Controller | Auth |
|---|---|---|---|
POST |
/wp-json/sparxstar/v1/device |
SirusRESTController |
WP nonce required |
GET |
/wp-json/sparxstar/v1/context |
SirusRESTController |
WP nonce required |
POST |
/wp-json/sparxstar/v1/pulse |
SirusRESTController |
WP nonce required; returns HttpOnly/SameSite=Strict pulse cookie |
GET |
/wp-json/sparxstar/v1/identity |
SirusRESTController |
WP nonce required |
GET |
/wp-json/sparxstar/v1/session |
SirusRESTController |
WP nonce required |
POST |
/wp-json/sparxstar/v1/client-report |
SirusRESTController |
WP nonce required; telemetry is never stored in post meta |
device_id, when supplied to /context, /identity, or /session, must match the current or token-derived Sirus device context; mismatches are rejected instead of returning another context shape.
All stable filters. Do not remove.
| Filter | Default | Where it is applied |
|---|---|---|
sparxstar_sirus_device_ttl_days |
90 |
DeviceRecord — device record TTL in days |
sparxstar_env_retention_days |
30 |
SirusEventRepository — event log retention |
sparxstar_sirus_capabilities |
[] |
CapabilityEngine — capability set for a context |
sparxstar_env_geolocation_lookup |
null |
EnvironmentResolver / StarUserEnv — custom geolocation provider |
sparxstar_env_geolocation_ttl |
DAY_IN_SECONDS |
GeoIP service — geolocation cache duration |
sparxstar_env_network_effective_type |
'unknown' |
EnvironmentResolver — override network type |
sparxstar_sirus_pulse_ttl_seconds |
120/60/30 by ResourceSensitivity level |
PulseGenerator::resolveTtl() — override the pulse TTL (seconds) before the LEVEL_1 low-connectivity extension is applied; receives ($ttl, $sensitivity, $default) |
| Option key | Owner | Purpose |
|---|---|---|
sirus_technical_consent_default |
ConsentManager |
Site authority default for technical consent |
sirus_mitigation_enabled |
SirusMitigationCoordinator |
Kill switch for mitigation system |
| Class | Canonical namespace | Notes |
|---|---|---|
ContextBootException |
Starisian\Sparxstar\Infrastructure\Exceptions |
Imported by Sirus; never redefine locally. |
ContextPulse |
Starisian\Sparxstar\Infrastructure\DTOs |
Imported by Sirus; generated here, verified by Helios. |
ContextPulseSigningMaterial |
Starisian\Sparxstar\Infrastructure\Utils |
Canonical HMAC signing material builder. |
Required at plugin load time:
| Constant | Required | Purpose |
|---|---|---|
SPARXSTAR_PULSE_SIGNING_KEY |
Only when PulseGenerator is called |
HMAC-SHA256 signing key. Minimum 32 bytes. |
ABSPATH |
Always | WordPress bootstrap guard. |
SIRUS_VERSION |
Auto-defined by entry point | Plugin version string. |
SIRUS_PLUGIN_PATH |
Auto-defined by entry point | Absolute path to plugin root. |
Do not expect these from this repository:
- Agreement evaluation (proceed/deny) → Helios
- KV-store revocation → Helios
- JWT issuance → Helios
- Governance policy evaluation → Mehns
- Structured field persistence → Dheghom
- Pulse verification — Sirus generates; Helios verifies
wp_set_auth_cookie()calls → prohibited in this repo
Last updated: 2026-06-09 | Spec version: Sirus Context Engine Spec v3.0