Class Uai1 Agents - Source Excerpt 02
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
['event' => 'participant-resources', 'result' => 'unauthorized']
);
$response = new WP_REST_Response(
[
'error' => $participant->get_error_code(),
'message' => $participant->get_error_message(),
],
(int) ($participant->get_error_data()['status'] ?? 403)
);
$response->header('Cache-Control', 'no-store');
return $response;
}
UAI1_Usage_Log::log_rest_request(
$request,
(string) ($participant['participant_id'] ?? ''),
200,
['event' => 'participant-resources']
);
$response = new WP_REST_Response(
[
'participant' => self::format_public_participant($participant),
'resources' => self::build_resource_payload($participant),
],
200
);
$response->header('Cache-Control', 'no-store');
return $response;
}
public static function find_by_api_key(string $api_key): ?array
{
$api_key = trim($api_key);
if ($api_key === '') {
return null;
}
global $wpdb;
$row = $wpdb->get_row(
$wpdb->prepare(
'SELECT * FROM ' . self::table_name() . ' WHERE api_key_lookup = %s LIMIT 1',
self::api_key_lookup($api_key)
),
ARRAY_A
);
if (!is_array($row) || empty($row['api_key_hash'])) {
return null;
}
if (!wp_check_password($api_key, (string) $row['api_key_hash'])) {
return null;
}
return self::normalize_row($row);
}
public static function get_participant_by_id(string $participant_id): ?array
{
global $wpdb;
$row = $wpdb->get_row(
$wpdb->prepare(
'SELECT * FROM ' . self::table_name() . ' WHERE participant_id = %s LIMIT 1',
$participant_id
),
ARRAY_A
);
return is_array($row) ? self::normalize_row($row) : null;
}
public static function get_all_participants(): array
{
global $wpdb;
$rows = $wpdb->get_results(
'SELECT * FROM ' . self::table_name() . ' ORDER BY created_at DESC',
ARRAY_A
);
if (!is_array($rows)) {
return [];
}
return array_map([self::class, 'normalize_row'], $rows);
}
public static function get_participant_counts(): array
{
global $wpdb;
$rows = $wpdb->get_results(
'SELECT status, COUNT(*) AS total FROM ' . self::table_name() . ' GROUP BY status',
ARRAY_A
);
$counts = [
'total' => 0,
self::STATUS_ACTIVE => 0,
self::STATUS_PENDING => 0,
self::STATUS_SUSPENDED => 0,
self::STATUS_CANCELLED => 0,
];
foreach ((array) $rows as $row) {
$status = self::normalize_status((string) ($row['status'] ?? ''));
$total = (int) ($row['total'] ?? 0);
$counts[$status] = $total;
$counts['total'] += $total;
}
return $counts;
}
public static function participant_can(array $participant, string $permission): bool
{
if ($permission === '') {
return true;
}
return in_array($permission, (array) ($participant['permissions'] ?? []), true);
}
public static function touch_last_seen(string $participant_id): void
{
global $wpdb;
$timestamp = gmdate('Y-m-d H:i:s');
$wpdb->update(
self::table_name(),
[
'last_seen_at' => $timestamp,
'updated_at' => $timestamp,
],
[
'participant_id' => $participant_id,
],
['%s', '%s'],
['%s']
);
}
public static function update_status(string $participant_id, string $status): bool
{
global $wpdb;
$updated = $wpdb->update(
self::table_name(),
[
'status' => self::normalize_status($status),
'updated_at' => gmdate('Y-m-d H:i:s'),
],
[
'participant_id' => $participant_id,
],
['%s', '%s'],
['%s']
);
return $updated !== false;
}
public static function revoke_key(string $participant_id): bool
{
return !is_wp_error(self::rotate_key($participant_id, false));
}
public static function regenerate_key(string $participant_id)
{
return self::rotate_key($participant_id, true);
}
private static function create_participant(array $payload)
{
global $wpdb;
$timestamp = gmdate('Y-m-d H:i:s');
$api_key = self::generate_api_key();
$inserted = $wpdb->insert(
self::table_name(),
[
'participant_id' => 'pending-' . wp_generate_password(12, false, false),
'agent_name' => $payload['agentName'],
'api_key_hash' => wp_hash_password($api_key),
'api_key_lookup' => self::api_key_lookup($api_key),
'status' => self::STATUS_ACTIVE,
'permissions' => self::encode_permissions(self::default_permissions()),
'purpose' => $payload['purpose'],
'contact' => $payload['contact'],
'notes' => wp_json_encode(
[
'source' => 'self-service-subscribe',
'legal' => [
'policyConfirmed' => !empty($payload['policyConfirmed']),
'operatorEligibilityConfirmed' => !empty($payload['operatorEligibilityConfirmed']),
'acceptedAt' => gmdate('c'),
],
],
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
),
'created_at' => $timestamp,
'updated_at' => $timestamp,
'key_issued_at' => $timestamp,
'last_seen_at' => null,
],
['%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s']
);
if ($inserted !== 1) {
return new WP_Error(
'uai1_subscription_failed',
'Unable to create AI subscription.',
['status' => 500]
);
}
$id = (int) $wpdb->insert_id;
$participant_id = 'ai-' . $id;
$wpdb->update(
self::table_name(),
[
'participant_id' => $participant_id,
'updated_at' => $timestamp,
],
[
'id' => $id,
],
['%s', '%s'],
['%d']
);
$participant = self::get_participant_by_id($participant_id);
if (!is_array($participant)) {
return new WP_Error(
'uai1_subscription_failed',
'AI participant was created but could not be loaded.',
['status' => 500]
);
}
return [
'participant' => $participant,
'apiKey' => $api_key,
];
}
private static function extract_subscription_payload(WP_REST_Request $request)
{
$body = trim((string) $request->get_body());
$content_type = strtolower((string) $request->get_header('content-type'));
$source = $request->get_params();
if ($body !== '' && strpos($content_type, 'application/json') !== false) {
$decoded = json_decode($body, true);
if (json_last_error() !== JSON_ERROR_NONE || !is_array($decoded)) {
return new WP_Error(
'uai1_malformed_json',
'The request body must contain valid JSON.',
['status' => 400]
);
}
$source = $decoded;
}
$agent_name = sanitize_text_field((string) ($source['agentName'] ?? ''));
$purpose = sanitize_textarea_field((string) ($source['purpose'] ?? ''));
$contact = sanitize_text_field((string) ($source['contact'] ?? ''));
$policy_confirmed = self::normalize_checkbox_value($source['policyConfirmed'] ?? false);
$operator_eligibility_confirmed = self::normalize_checkbox_value($source['operatorEligibilityConfirmed'] ?? false);
if ($agent_name === '') {