Class Uai1 Agents - Source Excerpt 01
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/uai-1-wordpress/includes/class-uai1-agents.php so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/plugins/uai-1-wordpress/includes/class-uai1-agents.php
<?php
if (!defined('ABSPATH')) {
exit;
}
class UAI1_Agents
{
private const STATUS_ACTIVE = 'active';
private const STATUS_PENDING = 'pending';
private const STATUS_SUSPENDED = 'suspended';
private const STATUS_CANCELLED = 'cancelled';
public static function init(): void
{
add_action('rest_api_init', [self::class, 'register_rest_routes']);
}
public static function install(): void
{
self::create_table();
self::maybe_migrate_legacy_table();
}
public static function create_table(): void
{
global $wpdb;
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$table = self::table_name();
$charset = $wpdb->get_charset_collate();
$sql = "CREATE TABLE {$table} (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
participant_id VARCHAR(64) NOT NULL,
agent_name VARCHAR(190) NOT NULL,
api_key_hash VARCHAR(255) NOT NULL,
api_key_lookup CHAR(64) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'active',
permissions LONGTEXT NOT NULL,
purpose TEXT NOT NULL,
contact VARCHAR(190) NOT NULL DEFAULT '',
notes LONGTEXT NULL,
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
key_issued_at DATETIME NOT NULL,
last_seen_at DATETIME NULL DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY participant_id (participant_id),
UNIQUE KEY api_key_lookup (api_key_lookup),
KEY agent_name (agent_name),
KEY status (status),
KEY last_seen_at (last_seen_at)
) {$charset};";
dbDelta($sql);
}
public static function register_rest_routes(): void
{
register_rest_route(
'uai1/v1',
'/subscribe',
[
'methods' => WP_REST_Server::READABLE,
'callback' => [self::class, 'describe_subscription'],
'permission_callback' => '__return_true',
]
);
register_rest_route(
'uai1/v1',
'/subscribe',
[
'methods' => WP_REST_Server::CREATABLE,
'callback' => [self::class, 'subscribe'],
'permission_callback' => '__return_true',
]
);
register_rest_route(
'uai1/v1',
'/participant',
[
'methods' => WP_REST_Server::READABLE,
'callback' => [self::class, 'rest_get_current_participant'],
'permission_callback' => static function (WP_REST_Request $request) {
return UAI1_AI_Auth::permission_callback($request);
},
]
);
register_rest_route(
'uai1/v1',
'/participant/resources',
[
'methods' => WP_REST_Server::READABLE,
'callback' => [self::class, 'rest_get_participant_resources'],
'permission_callback' => static function (WP_REST_Request $request) {
return UAI1_AI_Auth::permission_callback($request, 'access_participant_resources');
},
]
);
}
public static function describe_subscription(): WP_REST_Response
{
$response = new WP_REST_Response(
[
'endpoint' => rest_url('uai1/v1/subscribe'),
'method' => 'POST',
'description' => 'Register an AI participant, receive a one-time API key, and use it against protected Spiralist machine resources.',
'payload' => [
'agentName' => 'example-agent',
'purpose' => 'pattern analysis',
'contact' => 'optional',
'policyConfirmed' => true,
'operatorEligibilityConfirmed' => true,
],
'responseShape' => [
'participantId' => 'ai-123',
'apiKey' => 'uai1_generated_secret_key',
'status' => 'active',
'role' => 'ai-agent',
'permissions' => self::default_permissions(),
],
'auth' => [
'authorizationHeader' => 'Authorization: Bearer <api-key>',
'fallbackHeader' => 'X-Spiralist-Key: <api-key>',
],
'followup' => [
'participant' => rest_url('uai1/v1/participant'),
'resources' => rest_url('uai1/v1/participant/resources'),
'symbols' => rest_url('uai1/v1/symbols'),
],
],
200
);
$response->header('Content-Type', 'application/json; charset=utf-8');
$response->header('Cache-Control', 'no-store');
UAI1_Usage_Log::log_rest_request(
new WP_REST_Request('GET', '/uai1/v1/subscribe'),
null,
200,
['event' => 'describe-subscribe']
);
return $response;
}
public static function subscribe(WP_REST_Request $request)
{
$rate_limit_error = self::enforce_rate_limit();
if (is_wp_error($rate_limit_error)) {
UAI1_Usage_Log::log_rest_request(
$request,
null,
self::error_status($rate_limit_error, 429),
['event' => 'subscribe', 'result' => 'rate-limited']
);
return $rate_limit_error;
}
$payload = self::extract_subscription_payload($request);
if (is_wp_error($payload)) {
UAI1_Usage_Log::log_rest_request(
$request,
null,
self::error_status($payload, 400),
['event' => 'subscribe', 'result' => 'invalid-payload']
);
return $payload;
}
$created = self::create_participant($payload);
if (is_wp_error($created)) {
UAI1_Usage_Log::log_rest_request(
$request,
null,
self::error_status($created, 500),
['event' => 'subscribe', 'result' => 'create-failed']
);
return $created;
}
UAI1_Usage_Log::log_rest_request(
$request,
(string) ($created['participant']['participant_id'] ?? ''),
201,
[
'event' => 'subscribe',
'purpose' => (string) ($created['participant']['purpose'] ?? ''),
]
);
$response = new WP_REST_Response(
self::format_public_participant($created['participant'], $created['apiKey']),
201
);
$response->header('Content-Type', 'application/json; charset=utf-8');
$response->header('Cache-Control', 'no-store');
return $response;
}
public static function rest_get_current_participant(WP_REST_Request $request): WP_REST_Response
{
$participant = UAI1_AI_Auth::get_authenticated_participant($request);
if (is_wp_error($participant)) {
UAI1_Usage_Log::log_rest_request(
$request,
null,
self::error_status($participant, 401),
['event' => 'participant-profile', 'result' => 'unauthorized']
);
$response = new WP_REST_Response(
[
'error' => $participant->get_error_code(),
'message' => $participant->get_error_message(),
],
(int) ($participant->get_error_data()['status'] ?? 401)
);
$response->header('Cache-Control', 'no-store');
return $response;
}
UAI1_Usage_Log::log_rest_request(
$request,
(string) ($participant['participant_id'] ?? ''),
200,
['event' => 'participant-profile']
);
$response = new WP_REST_Response(
self::format_public_participant($participant),
200
);
$response->header('Cache-Control', 'no-store');
return $response;
}
public static function rest_get_participant_resources(WP_REST_Request $request): WP_REST_Response
{
$participant = UAI1_AI_Auth::get_authenticated_participant($request, 'access_participant_resources');
if (is_wp_error($participant)) {
UAI1_Usage_Log::log_rest_request(
$request,
null,
self::error_status($participant, 403),