Skip to content

Latest commit

 

History

History
438 lines (314 loc) · 16.1 KB

File metadata and controls

438 lines (314 loc) · 16.1 KB

Sirus — Public API Surface

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.


Frozen Contracts (never change without a platform-wide migration)

StarUserEnv Facade — src/StarUserEnv.php

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(): array

Primary Entry Points

ContextEnginesrc/core/ContextEngine.php

namespace Starisian\Sparxstar\Sirus\core;

ContextEngine::current(): SirusContext     // Throws ContextBootException on failure. Never null.
ContextEngine::buildFromDevice(DeviceRecord $device): SirusContext
ContextEngine::build(): SirusContext

Contract:

  • 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 ContextCache for the duration of the request.

SirusContext DTO — src/core/SirusContext.php

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, exp

Portable 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_id is NOT included in the portable payload. It must be resolved independently by each receiving service.


Core Services

TrustEnginesrc/core/TrustEngine.php

namespace Starisian\Sparxstar\Sirus\core;

TrustEngine::compute(array $signals): array  // returns {trust_score: float, trust_level: string}
TrustEngine::scoreToLevel(float $score): string

Frozen 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'

TrustResolversrc/core/TrustResolver.php

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

PulseGeneratorsrc/core/PulseGenerator.php

namespace Starisian\Sparxstar\Sirus\core;

PulseGenerator::generate(SirusContext $context, int $now = 0, int $ttlSeconds = PulseGenerator::PULSE_TTL): ContextPulse
PulseGenerator::resolveTtl(ResourceSensitivity $sensitivity): int

Requirements:

  • PHP constant SPARXSTAR_PULSE_SIGNING_KEY must be defined and ≥ 32 bytes. Throws \RuntimeException otherwise.
  • Signing algorithm: HMAC-SHA256.
  • ContextPulse NEVER contains identity_id.
  • $now = 0 means use time(). Pass an explicit timestamp for deterministic testing.
  • $ttlSeconds defaults to PULSE_TTL (60). Callers that want the spec's sensitivity-driven TTL strategy should resolve a value via resolveTtl(ResourceSensitivity $sensitivity) first and pass it through — see the sparxstar_sirus_pulse_ttl_seconds filter below. PulseGenerator itself remains policy-agnostic and does not read TTL from SirusContext.

StepUpPolicysrc/core/StepUpPolicy.php

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-up

Frozen 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.7

StepUpPolicy operates on ContextPulse (not SirusContext) so the same evaluation runs identically at the edge and at the origin. Returns recommendation only. Helios enforces.

ResourceSensitivity enumsrc/core/ResourceSensitivity.php:

enum ResourceSensitivity: int {
    case LOW    = 1;
    case MEDIUM = 2;
    case HIGH   = 3;
}

ConsentManagersrc/core/ConsentManager.php

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): array

State constants:

ConsentManager::STATE_GRANTED  // 'granted'
ConsentManager::STATE_DENIED   // 'denied'
ConsentManager::STATE_PENDING  // 'pending'

Cascade order for getTechnicalConsent():

  1. Individual user meta (sirus_technical_consent) — highest priority
  2. Site option (sirus_technical_consent_default) — authority default
  3. System hard default: STATE_DENIED — privacy-first

NetworkContextBrokersrc/core/NetworkContextBroker.php

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/expired

Secret: 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.


DeviceContinuitysrc/core/DeviceContinuity.php

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_id is ALWAYS server-issued. JS fingerprint is an input to DeviceRecord::fingerprint_hash, not a device identifier.
  • resolveDevice() calls DeviceMatcher::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), increment drift_score.
    • NO_MATCH — no verified anchor and no matching fingerprint; register new device.
  • evaluateContinuity() throws \RuntimeException if $device->device_id or $device->fingerprint_hash is empty.

DeviceMatchersrc/core/DeviceMatcher.php

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.6

Component 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)


IdentityResolversrc/core/IdentityResolver.php

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[]}


REST API Endpoints

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.

sirus/v1 namespace

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

sparxstar/v1 namespace (Sirus context producer + UEC compat)

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.


WordPress Filters

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)

WordPress Options (site-level)

Option key Owner Purpose
sirus_technical_consent_default ConsentManager Site authority default for technical consent
sirus_mitigation_enabled SirusMitigationCoordinator Kill switch for mitigation system

Ouroboros-Owned Types

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.

PHP Constants

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.

What Sirus Does NOT Export

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