Skip to content
wiki.fftac.org

Restcontroller - Source Excerpt 08

Back to Restcontroller

Summary

This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/spiralist-workspace/includes/Http/RestController.php so readers can inspect the evidence without opening the full source file.

**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Http/RestController.php

return $user_id > 0 && ($this->permissions->is_admin($user_id) || user_can($user_id, 'share_prompts_with_specific_users'));
    }

    /**
     * Returns the next scheduled UTC timestamp for one cron hook.
     */
    private function scheduled_utc(string $hook): string
    {
        $timestamp = wp_next_scheduled($hook);

        return $timestamp ? gmdate('c', (int) $timestamp) : '';
    }

    /**
     * Returns one prompt payload enriched with review summary.
     */
    private function augment_prompt_payload(array $prompt, bool $detail): array
    {
        $record = $this->prompts->for_api($prompt, $detail);
        $prompt_id = (int) ($prompt['id'] ?? 0);
        $record['appeal_summary'] = $this->appeals->summary_for_prompt($prompt_id);
        $record['review_summary'] = $this->current_review_summary($prompt_id, $record['appeal_summary']);
        $record['governance_summary'] = PromptGovernanceSummary::build(
            $record,
            $record['review_summary'],
            $record['appeal_summary']
        );

        return $record;
    }

    /**
     * Reconciles moderation state after a peer-review or report signal.
     */
    private function reconcile_prompt_governance(array $prompt, int $actor_user_id, string $trigger): array
    {
        if (empty($prompt)) {
            return [];
        }

        $appeal_summary = $this->appeals->summary_for_prompt((int) $prompt['id']);
        $summary = $this->current_review_summary((int) $prompt['id'], $appeal_summary);
        $current = PromptMetaRegistry::normalize_moderation_status((string) ($prompt['moderation_status'] ?? 'draft'));
        $target = $this->resolve_governance_status($prompt, $summary, $appeal_summary);

        if ($target === $current) {
            return $this->prompts->get((int) $prompt['id'], $actor_user_id);
        }

        $updated = $this->prompts->set_moderation_status((int) $prompt['id'], $target);
        $this->audit->log(
            $actor_user_id ?: null,
            'prompt_moderation_state_changed',
            'prompt',
            (int) $prompt['id'],
            [
                'from' => $current,
                'to' => $target,
                'trigger' => $trigger,
                'summary' => $summary,
                'appeal_summary' => $appeal_summary,
            ]
        );

        return $updated;
    }

    /**
     * Resolves the stored moderation state from peer-review and report counts.
     *
     * @param array<string,mixed> $summary
     */
    private function resolve_governance_status(array $prompt, array $summary, array $appeal_summary = []): string
    {
        $visibility = (string) ($prompt['visibility'] ?? 'private');
        $prompt_status = (string) ($prompt['prompt_status'] ?? 'draft');

        if ($prompt_status === 'archived') {
            return 'archived';
        }

        if ($visibility !== 'public' || $prompt_status !== 'published') {
            return 'draft';
        }

        if ((string) ($appeal_summary['latest_resolution'] ?? '') === 'archive') {
            return 'archived';
        }

        $restrict = (int) (($summary['peer']['restrict'] ?? 0));
        $revert = (int) (($summary['peer']['revert'] ?? 0));
        $endorse = (int) (($summary['peer']['endorse'] ?? 0));
        $reports = (int) ($summary['unique_reporters'] ?? 0);
        $current = PromptMetaRegistry::normalize_moderation_status((string) ($prompt['moderation_status'] ?? 'draft'));

        if ($revert >= 2) {
            return 'reverted';
        }

        if ($restrict >= 2 || $reports >= 3) {
            return 'restricted_review';
        }

        if ($endorse >= 2) {
            return (string) ($prompt['publication_lane'] ?? 'community_library') === 'official_canon'
                ? 'official_canon'
                : 'peer_reviewed';
        }

        if ((string) ($prompt['prompt_origin'] ?? 'user') === 'system' && in_array($current, ['peer_reviewed', 'official_canon'], true)) {
            return $current;
        }

        if (in_array($current, ['peer_reviewed', 'official_canon'], true) && $endorse === 0 && $restrict === 0 && $reports === 0) {
            return $current;
        }

        if ((string) ($appeal_summary['latest_resolution'] ?? '') === 'restore') {
            return 'provisional_public';
        }

        return 'provisional_public';
    }

    /**
     * Returns the active review summary after appeal-based governance resets.
     *
     * @param array<string,mixed>|null $appeal_summary
     * @return array<string,mixed>
     */
    private function current_review_summary(int $prompt_id, ?array $appeal_summary = null): array
    {
        if ($appeal_summary === null) {
            $appeal_summary = $this->appeals->summary_for_prompt($prompt_id);
        }

        $since_utc = (string) ($appeal_summary['governance_reset_utc'] ?? '');

        return $this->reviews->summary_for_prompt($prompt_id, $since_utc);
    }

    /**
     * Returns whether a prompt is safe for public-library exposure.
     */
    private function is_public_library_prompt(array $prompt): bool
    {
        return (string) ($prompt['visibility'] ?? '') === 'public'
            && empty($prompt['soft_deleted_at'])
            && (string) ($prompt['prompt_status'] ?? 'draft') === 'published'
            && PromptMetaRegistry::is_public_moderation_status((string) ($prompt['moderation_status'] ?? 'draft'));
    }

    /**
     * Blocks public publication when attached Spiral Script source fails v0.1 validation.
     *
     * @param array<string,mixed> $payload
     * @param array<string,mixed> $fallback
     */
    private function validate_spiral_script_publication_request(array $payload, array $fallback, int $user_id): ?WP_Error
    {
        if (!function_exists('spiralist_spiral_script_compile')) {
            return null;
        }

        $source = trim((string) (
            $payload['spiral_script_source']
            ?? ($payload['spiralist_workspace_spiral_script_source']
            ?? ($fallback['spiral_script_source'] ?? ''))
        ));

        if ($source === '') {
            return null;
        }

        $visibility = sanitize_key((string) (
            $payload['visibility']
            ?? ($payload['spiralist_workspace_visibility']
            ?? ($fallback['visibility'] ?? 'private'))
        ));
        $prompt_status = sanitize_key((string) (
            $payload['prompt_status']
            ?? ($payload['spiralist_workspace_prompt_status']
            ?? ($fallback['prompt_status'] ?? 'draft'))
        ));
        $attempting_publication = $visibility === 'public' || $prompt_status === 'published';

        if (!$attempting_publication) {
            return null;
        }

        $compiled = spiralist_spiral_script_compile(
            $source,
            [
                'title' => (string) ($payload['title'] ?? ($fallback['title'] ?? 'Untitled Prompt')),
                'visibility' => $visibility,
                'createdBy' => $user_id > 0 ? 'user:' . (string) $user_id : 'anonymous',
                'createdAt' => gmdate('c'),
            ]
        );
        $validation = is_array($compiled['validation'] ?? null) ? (array) $compiled['validation'] : [];

        if (!empty($validation['passed'])) {
            return null;
        }

        $blocking = array_values(array_filter(
            (array) ($validation['errors'] ?? []),
            static function ($error): bool {
                return is_array($error) && in_array((string) ($error['severity'] ?? ''), ['blocker', 'error'], true);
            }
        ));

        if (empty($blocking)) {
            return null;
        }

        return new WP_Error(
            'spiralist_workspace_spiral_script_invalid',
            'Spiral Script validation must pass before a prompt can be public or published.',
            [
                'status' => 400,
                'spiral_script_validation' => $validation,
            ]
        );
    }

    /**
     * Returns prompt-library filters from a REST request.
     *
     * @return array<string,string>
     */
    private function request_filters(WP_REST_Request $request): array
    {
        $search = sanitize_text_field((string) $request->get_param('search'));
        $intent = trim((string) $request->get_param('intent')) !== ''
            ? PromptIntentRegistry::normalize_intent((string) $request->get_param('intent'))
            : '';
        $redirect_intent = $intent === '' ? PromptIntentRegistry::redirect_intent_for_search($search) : '';
        if ($redirect_intent !== '') {
            $intent = $redirect_intent;
        }

        return [
            'intent' => $intent,