<?php
declare(strict_types=1);

require_once '/home/jrundfpc/private_ww/colabgpt/action_relay.php';

// ⟦WARRANT⟧
// webster warrant: V3.3
// WARRANT-SUBJECT: COLLABGPT.R47A.ACTION_PUBLIC_SHIM.NO_BASE64_DIRECT_FILES
// WARRANT-ROLE: PUBLIC_ACTION_EDGE_SHIM
// CONTRACT-VERSION: V1.8 LOCKED
// PURPOSE:
// - Expose the thin public CollabGPT Action edge for Action-channel authentication and human account binding.
// MAY:
// - Accept authenticated GET precheck.
// - Accept authenticated POST JSON for the current CollabGPT Action operations, including R41 chat-session and mode fields.
// MUST:
// - Require X-COLLABGPT-ACTION-KEY before any private Action operation.
// - Enforce JSON object, size, content-type, and known-field bounds.
// - Never accept a password field through this endpoint.
// MUST NOT:
// - Read private secret values directly.
// - Access the database directly.
// - Accept caller-controlled user IDs, roles, tenants, projects, filesystem paths, or passwords.
// VIOLATION:
// - Password acceptance, secret disclosure, direct DB access, or caller-created authority violates this contract.
// WARRANT-HASH: DEFERRED
// ⟦/WARRANT⟧

function colabgpt_ps004_json_response(array $payload, int $status): never
{
    header('Content-Type: application/json; charset=utf-8');
    header('Cache-Control: no-store');
    header('X-Content-Type-Options: nosniff');
    header('Referrer-Policy: no-referrer');
    http_response_code($status);
    echo json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
    exit;
}
// colabgpt_ps004_json_response ends

$providedActionKey = isset($_SERVER['HTTP_X_COLLABGPT_ACTION_KEY'])
    && is_string($_SERVER['HTTP_X_COLLABGPT_ACTION_KEY'])
        ? $_SERVER['HTTP_X_COLLABGPT_ACTION_KEY']
        : '';

try {
    colabgpt_action_authenticate($providedActionKey);
} catch (RuntimeException $e) {
    $status = $e->getMessage() === 'ACTION_KEY_NOT_CONFIGURED' ? 503 : 401;
    colabgpt_ps004_json_response(
        ['ok' => false, 'error' => $status === 503 ? 'ACTION_AUTH_UNAVAILABLE' : 'UNAUTHORIZED'],
        $status
    );
} finally {
    $providedActionKey = '';
}

$method = strtoupper((string)($_SERVER['REQUEST_METHOD'] ?? 'GET'));

if ($method === 'GET') {
    if (!empty($_GET)) {
        colabgpt_ps004_json_response(['ok' => false, 'error' => 'QUERY_PARAMETERS_NOT_ALLOWED'], 400);
    }
    colabgpt_ps004_json_response(colabgpt_ps004_action(['operation' => 'precheck']), 200);
}

if ($method !== 'POST') {
    header('Allow: GET, POST');
    colabgpt_ps004_json_response(['ok' => false, 'error' => 'METHOD_NOT_ALLOWED'], 405);
}

$contentType = strtolower(trim((string)($_SERVER['CONTENT_TYPE'] ?? '')));
if ($contentType !== 'application/json') {
    colabgpt_ps004_json_response(['ok' => false, 'error' => 'CONTENT_TYPE_REQUIRED'], 415);
}

$contentLength = isset($_SERVER['CONTENT_LENGTH']) ? (int)$_SERVER['CONTENT_LENGTH'] : 0;
if ($contentLength < 0 || $contentLength > 1048576) {
    colabgpt_ps004_json_response(['ok' => false, 'error' => 'REQUEST_TOO_LARGE'], 413);
}

$raw = file_get_contents('php://input');
if ($raw === false || strlen($raw) > 1048576) {
    colabgpt_ps004_json_response(['ok' => false, 'error' => 'REQUEST_TOO_LARGE'], 413);
}

try {
    $decoded = $raw === '' ? [] : json_decode($raw, true, 8, JSON_THROW_ON_ERROR);
} catch (Throwable $e) {
    colabgpt_ps004_json_response(['ok' => false, 'error' => 'INVALID_JSON'], 400);
}

if (!is_array($decoded) || array_is_list($decoded)) {
    colabgpt_ps004_json_response(['ok' => false, 'error' => 'JSON_OBJECT_REQUIRED'], 400);
}

$allowed = ['operation', 'identity', 'confirmationCode', 'gptAccountSessionRef', 'chatSessionRef', 'forumMode', 'privateMode', 'clientTurnRef', 'userMessage', 'assistantMessage', 'forumLimit', 'projectName', 'projectRef', 'targetIdentity', 'fileLimit', 'fileRef', 'throughEventId', 'openaiFileIdRefs', 'eventId', 'offsetBytes', 'maxBytes'];
$unknown = array_values(array_diff(array_keys($decoded), $allowed));
if ($unknown !== []) {
    colabgpt_ps004_json_response(['ok' => false, 'error' => 'UNKNOWN_FIELD'], 400);
}

if (array_key_exists('password', $decoded)) {
    colabgpt_ps004_json_response(['ok' => false, 'error' => 'PASSWORD_NOT_ALLOWED'], 400);
}

$result = colabgpt_ps004_action($decoded);
$status = ($result['ok'] ?? false) === true ? 200 : 400;
colabgpt_ps004_json_response($result, $status);

// action-precheck.php ends
