Connor Yoh 6eb41b6931 payg(c4): annotate AI controllers + tag InternalApiClient sub-steps as AUTOMATION
The saas PaygChargeInterceptor classifies a request as AI / AUTOMATION /
API / BYPASSED using a fixed precedence: X-Stirling-Automation header >
@RequiresFeature(AUTOMATION) > @RequiresFeature(AI_SUPPORT) > API-key
auth > BYPASSED (manual UI).

Plug the AI surface and the automation sub-step path:

AI controllers (saas → easy import):
- AiCreateController, AiCreateInternalController, AiProxyController each
  get class-level @RequiresFeature(AI_SUPPORT). The interceptor already
  falls back to the bean type via AnnotationUtils.findAnnotation when no
  method-level annotation is present.

Automation sub-step header (InternalApiClient in common):
- Every caller of InternalApiClient.post() is a parent automation flow
  (PipelineProcessor, AiWorkflowService, PolicyExecutor) running a child
  tool via loopback HTTP. Tag every dispatch with
  X-Stirling-Automation: true so the child step bills as AUTOMATION
  regardless of its own annotation — i.e. an AI-OCR step inside a
  policy run is correctly billed AUTOMATION rather than AI.

Deviation (documented in test javadoc): PipelineController lives in
core and PolicyController lives in proprietary. Neither module can
import @RequiresFeature from saas without a forbidden upward dependency
(both build under STIRLING_FLAVOR=core/proprietary where saas is
absent). Promoting RequiresFeature + FeatureGate to common is a
non-trivial refactor (touches 18 files across multiple C-bucket
commits) and out of scope for C4. The X-Stirling-Automation header
covers sub-step dispatch via InternalApiClient; direct user-facing
calls to /api/v1/pipeline/handleData therefore bill as BYPASSED (WEB)
or API (api-key auth) rather than AUTOMATION. Annotating those
controllers is left to a future refactor that promotes the cap types
to common.

Tests:
- RequiresFeatureAnnotationRolloutTest pins the AI controller
  classifications so a refactor can't silently regress to BYPASSED.
- InternalApiClientTest.postTagsRequestAsAutomation captures the
  HttpHeaders submitted to RestTemplate and asserts the marker.
2026-06-09 14:48:36 +01:00
2026-06-02 16:08:24 +00:00
2026-06-03 16:16:33 +00:00
2026-06-02 16:08:24 +00:00
2026-05-22 13:40:34 +01:00
2026-03-25 11:00:40 +00:00
2026-06-02 16:08:24 +00:00
2026-03-25 11:00:40 +00:00

Stirling PDF logo

Stirling PDF - The Open-Source PDF Platform

Stirling PDF is a powerful, open-source PDF editing platform. Run it as a personal desktop app, in the browser, or deploy it on your own servers with a private API. Edit, sign, redact, convert, and automate PDFs without sending documents to external services.

Docker Pulls Discord OpenSSF Scorecard GitHub Repo stars

Stirling PDF - Dashboard

Key Capabilities

  • Everywhere you work - Desktop client, browser UI, and self-hosted server with a private API.
  • 50+ PDF tools - Edit, merge, split, sign, redact, convert, OCR, compress, and more.
  • Automation & workflows - No-code pipelines direct in UI with APIs to process millions of PDFs.
  • Enterprisegrade - SSO, auditing, and flexible onprem deployments.
  • Developer platform - REST APIs available for nearly all tools to integrate into your existing systems.
  • Global UI - Interface available in 40+ languages.

For a full feature list, see the docs: https://docs.stirlingpdf.com

Quick Start

docker run -p 8080:8080 docker.stirlingpdf.com/stirlingtools/stirling-pdf

Then open: http://localhost:8080

For full installation options (including desktop and Kubernetes), see our Documentation Guide.

Resources

Support

Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

This project uses Task as a unified command runner for all build, dev, and test commands. Run task install to get started, or see the Developer Guide for full details.

For adding translations, see the Translation Guide.

License

Stirling PDF is open-core. See LICENSE for details.

Languages
Java 49.9%
TypeScript 39.9%
Python 4.3%
CSS 2.7%
Shell 0.9%
Other 2.2%