CCC: Refactor to harden function-call plugin / runtime surface (GetAiRelevantContext)
>>> [!note] Migrated issue
<!-- Drupal.org comment -->
<!-- Migrated from issue #3574910. -->
Reported by: [kristen pol](https://www.drupal.org/user/8389)
>>>
<p>[Tracker]<br>
<strong>Update Summary: </strong>[One-line status update for stakeholders]<br>
<strong>Check-in Date: </strong>MM/DD/YYYY<br>
<strong>Blocked by: </strong>[#XXXXXX] (New issues on new lines)<br>
<strong>Additional Collaborators: </strong> @username1, @username2<br>
<em>Metadata is used by the <a href="https://www.drupalstarforge.ai/" title="AI Tracker">AI Tracker.</a> Docs and additional fields <a href="https://www.drupalstarforge.ai/ai-dashboard/docs" title="AI Issue Tracker Documentation">here</a>.</em><br>
[/Tracker]</p>
<h3 id="summary-problem-motivation">Problem/Motivation</h3>
<p>Follow-up to:</p>
<p><span class="drupalorg-gitlab-issue-link project-issue-status-info project-issue-status-7"><a href="https://www.drupal.org/project/ai_context/issues/3573713" title="Status: Closed (fixed)">#3573713: Full architecture review of CCC in prep for 1.0</a></span></p>
<p><strong>Summary / goal</strong></p>
<p>Add authorization and structured logging around the FunctionCall plugin that exposes context selection (GetAiRelevantContext) so only authorized runtimes/callers can invoke it and calls are auditable.</p>
<p><strong>Why this matters</strong></p>
<p>GetAiRelevantContext exposes site context programmatically. Without caller validation it can be used to enumerate sensitive content or be invoked by untrusted runtimes. Adding auth + logging prevents abuse and improves traceability.</p>
<p><strong>Acceptance criteria</strong></p>
<ul>
<li>Unauthorized callers are rejected (unit tests simulate unauthorized caller -> plugin returns error/throws or no data).</li>
<li>Every successful invocation logs a structured audit entry including caller identity (user id or service id), agent_id, runner_id if provided, and request route/context.</li>
<li>Backwards-compatible: existing trusted runtimes still work when configured (clear migration path).</li>
<li>Tests verify both rejection and successful logged entries.</li>
</ul>
<h3 id="summary-proposed-resolution">Proposed resolution</h3>
<p><strong>Primary files</strong></p>
<ul>
<li>src/Plugin/AiFunctionCall/GetAiRelevantContext.php</li>
</ul>
<p><strong>Recommended implementation approach (directional)</strong></p>
<ul>
<li>Decide caller identity model: prefer server-side caller identity (current user / service account / API key) or host runtime-provided token. Document expected caller (e.g., internal agent runtime vs external).</li>
<li>Add an explicit permission check or runtime-auth check early in the plugin:
<ul>
<li>If invoked in HTTP request context, check current user permissions (view ai context items or a new invoke ai_context function permission).</li>
<li>If invoked by non-user runtimes, require a configured runtime token or allowlist and validate it via RequestStack or a configured auth service.</li>
</ul>
</li>
<li>Add structured logging (PSR-3) with placeholders: plugin id, agent_id, caller_id, runner_id, number of selected IDs, and duration. Use logger channel ai_context and avoid logging full context content.</li>
<li>Optionally add simple rate-limiting or quota checks per caller if discovery abuse is a concern.</li>
</ul>
<p><strong>Subtasks</strong></p>
<ol>
<li>[Decision] Choose caller auth model (permission vs runtime token/allowlist) and document behavior.</li>
<li>Implement auth check in plugin (inject current_user / requestStack / auth service) and return safe error on unauthorized calls.</li>
<li>Add structured logging of each call (success/failure) with minimal safe fields.</li>
<li>Add unit tests for authorized and unauthorized scenarios.</li>
<li>Update docs/README noting plugin security expectations and config.</li>
</ol>
<p><strong>Testing strategy</strong></p>
<ul>
<li>Unit tests that instantiate the plugin with mocked container and simulate:</li>
<li>Authorized caller: plugin executes and returns expected IDs/text; logger called with expected fields.</li>
<li>Unauthorized caller: plugin denies access (exception or empty result) and logs the denied attempt.</li>
<li>Integration test for host runtime scenario (if applicable) to verify configured token is accepted.</li>
</ul>
<p><strong>Risks & mitigations</strong></p>
<ul>
<li>Risk: Breaking existing integrations if auth model changes. Mitigate by supporting dual-mode (legacy allowed via config flag) and communicating change.</li>
<li>Risk: Overlogging sensitive text. Mitigate by logging metadata only (IDs, counts, caller id) and never full context content or prompt text.</li>
</ul>
<h3 id="summary-remaining-tasks">Target date or deadline</h3>
<p>February 2026</p>
<h3 id="summary-remaining-tasks">Remaining tasks</h3>
<ul>
<li>Review AI findings</li>
<li>Decide if they are correct</li>
<li>Decide if the proposed approach is best or propose alternative</li>
<li>Update code</li>
<li>Review and test</li>
</ul>
<h3 id="summary-ai-usage">AI usage (if applicable)</h3>
<p>[x] AI Assisted Issue<br>
This issue was generated with AI assistance, but was reviewed and refined by the creator.</p>
<p>[ ] AI Assisted Code<br>
This code was mainly generated by a human, with AI autocompleting or parts AI generated, but under full human supervision.</p>
<p>[ ] AI Generated Code<br>
This code was mainly generated by an AI with human guidance, and reviewed, tested, and refined by a human.</p>
<p>[ ] Vibe Coded<br>
This code was generated by an AI and has only been functionally tested.</p>
> Related issue: [Issue #3573713](https://www.drupal.org/node/3573713)
issue