{"id":51462500,"url":"https://github.com/dirnbauer/sg_apicore","last_synced_at":"2026-07-06T07:00:51.950Z","repository":{"id":358332830,"uuid":"1234024902","full_name":"dirnbauer/sg_apicore","owner":"dirnbauer","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-20T18:04:06.000Z","size":1605,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-20T19:21:22.047Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dirnbauer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-09T16:47:57.000Z","updated_at":"2026-06-20T18:04:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dirnbauer/sg_apicore","commit_stats":null,"previous_names":["dirnbauer/sg_apicore"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/dirnbauer/sg_apicore","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dirnbauer%2Fsg_apicore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dirnbauer%2Fsg_apicore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dirnbauer%2Fsg_apicore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dirnbauer%2Fsg_apicore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dirnbauer","download_url":"https://codeload.github.com/dirnbauer/sg_apicore/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dirnbauer%2Fsg_apicore/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35180933,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-06T02:00:07.184Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-06T07:00:50.939Z","updated_at":"2026-07-06T07:00:51.947Z","avatar_url":"https://github.com/dirnbauer.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ext: sg_apicore\n\n\u003cimg src=\"https://www.sgalinski.de/typo3conf/ext/project_theme/Resources/Public/Images/logo.svg\" alt=\"\"/\u003e\n\nLicense: [GNU GPL, Version 2 or later](https://www.gnu.org/licenses/gpl-2.0.html)\n\nRepository: https://github.com/dirnbauer/sg_apicore\n\nPlease report bugs here: https://github.com/dirnbauer/sg_apicore/issues\n\n## Short Summary\n\nProvides an API framework for TYPO3: multi-API and multi-version routing, site-aware tenants, attribute-based endpoint\nconfiguration, OpenAPI output, structured logging, opaque bearer tokens, JWT user tokens, backend-session auth,\nMCP tool exposure, Auto-CRUD resources, and custom endpoints.\n\nVersion `14.x` is TYPO3 v14-only. The package requires TYPO3 `^14.3`, `typo3/cms-workspaces` `^14.3`, and PHP `^8.3`.\nTYPO3 13 compatibility is intentionally not maintained in this release line.\n\nFor detailed information, please refer to the documentation in [docs/](docs/).\nFor website-ready end-user communication, see `docs/Website-End-User-Documentation.md`.\n\n## Directory Structure\n\nThe extension follows a standard TYPO3 extension structure with a focus on clean separation of concerns:\n\n- `Classes/`\n    - `Attribute/`: PHP attributes for routing, configuration, and security (e.g., `#[ApiRoute]`, `#[RequireScopes]`).\n    - `Configuration/`: Configuration readers and objects.\n    - `Context/`: Value objects for request context (e.g., `TenantContext`).\n    - `Controller/`: API controllers handling the requests.\n    - `Domain/`:\n        - `Repository/`: Repositories for database access (e.g., `TokenRepository`).\n    - `Middleware/`: PSR-15 middlewares (e.g., `ApiRequestMiddleware` for request interception).\n    - `Security/`: Authentication and authorization logic (e.g., `BearerTokenProvider`, `AuthContext`).\n    - `Service/`\n        - `Tenant/`: Tenant resolution logic and resolvers.\n        - `ApiRegistry.php`: Service to register APIs and versions.\n        - `Router.php`: FastRoute-based dispatcher.\n- `Configuration/`: TYPO3 configuration files (Services, Middlewares, TCA).\n- `docs/`: Technical documentation and guides.\n- `tests/`: Unit and functional tests.\n\n## Installation\n\n1. Install the extension via composer:\n   ```bash\n   composer require sgalinski/sg-apicore\n   ```\n\n2. Activate the extension in the TYPO3 Extension Manager.\n\n3. Make sure `typo3/cms-workspaces` is installed if Auto-CRUD writes should stage changes in a non-live workspace.\n\n## Documentation\n\n- [APIs and registration](docs/APIs.md)\n- [Writing endpoints](docs/WritingEndpoints.md)\n- [Authentication and scopes](docs/AuthScopes.md)\n- [Auto-CRUD resources](docs/Resources.md)\n- [TCA mapper](docs/TcaMapper.md)\n- [OpenAPI](docs/OpenAPI.md)\n- [MCP integration](docs/MCP.md)\n- [Rate limiting](docs/RateLimiting.md)\n- [Tenants](docs/Tenants.md)\n- [Logging](docs/Logging.md)\n- [Migration from sg_rest](docs/Migration.md)\n\n## Development Quality Gates\n\nThe repository ships PHPStan configuration adapted from the TYPO3 v14.3 core setup and runs at max level:\n\n```bash\ncomposer phpstan\ncomposer test\nBuild/Scripts/runTests.sh -s ci -p 8.3\n```\n\nThe CI runner performs PHP linting, PHPStan at `level: max`, PHPUnit, and Composer audit.\n\nOlder `ddev-demo-setup-visual-editor` Composer files patched `sgalinski/sg-apicore` while the TYPO3 v14 upgrade branch\nwas still external. Those patch changes are now part of this repository, so this extension does not include a Composer\npatch setup. The current demo project still uses `cweagans/composer-patches` for a `friendsoftypo3/content-blocks`\nproject patch, which does not belong in this extension package.\n\n## Quick Start (3 Steps)\n\n### 1. Register your Controller\n\nAdd your controller to `Configuration/Services.php` and tag it with `sg_apicore.router`:\n\n```php\n$services-\u003eset(MyController::class)\n    -\u003etag('sg_apicore.router');\n```\n\n### 2. Define an Endpoint\n\nUse the `#[ApiRoute]` attribute in your controller action:\n\n```php\n#[ApiRoute(path: '/hello', methods: ['GET'])]\npublic function helloAction(ServerRequestInterface $request): ResponseInterface {\n    return $this-\u003eresponseService-\u003ecreateSuccessResponse(['message' =\u003e 'Hello!']);\n}\n```\n\n### 3. Access the API\n\nOpen your browser at `https://your-domain.local/api/docs/ui/` to see the generated Swagger UI and test your new\nendpoint!\n\n## Testing\n\nYou can test the API by calling the health endpoint:\n\n```bash\n# Basic health check\ncurl https://your-project.local/api/health\n\n# API-specific health check (if registered)\ncurl https://your-project.local/api/public/v1/health\n```\n\nThe API path prefix is configurable via the extension configuration (default: `/api/`).\n\n## API Registration\n\nTo register a new API, you use the `ApiRegistry` service. Detailed configuration options can be found in\nthe [APIs \u0026 Registration Documentation](docs/APIs.md).\n\n```php\nuse SGalinski\\SgApiCore\\Service\\ApiRegistry;\nuse TYPO3\\CMS\\Core\\Utility\\GeneralUtility;\n\n$apiRegistry = GeneralUtility::makeInstance(ApiRegistry::class);\n$apiRegistry-\u003eregisterApi('public', ['1']);\n```\n\n## Writing Endpoints\n\nEndpoints are defined using PHP attributes on controller methods. See [Writing Endpoints](docs/WritingEndpoints.md) for\na full guide.\nFor a complete template with current best practices, see [ExampleController](docs/examples/ExampleController.php).\n\n```php\n#[ApiRoute(path: '/my-endpoint', methods: ['GET'], apiId: 'public', version: '1')]\npublic function myAction(ServerRequestInterface $request): ResponseInterface {\n    return $this-\u003eresponseService-\u003ecreateSuccessResponse(['message' =\u003e 'Hello World']);\n}\n```\n\n### Standardized Responses\n\nThe `ResponseService` provides a unified way to create JSON responses, following RFC 7807 for errors.\nSee [Writing Endpoints - Responses](docs/WritingEndpoints.md#standardized-responses).\n\n### Pagination\n\nThe extension provides a `PaginationService` to handle consistent pagination across endpoints.\nSee [Writing Endpoints - Pagination](docs/WritingEndpoints.md#pagination).\n\n## TCA Mapper\n\nThe `TcaMapper` service allows you to map TYPO3 database records to API response arrays based on the TCA.\nSee [TCA Mapper Documentation](docs/TcaMapper.md).\n\n## Auto-CRUD Resources\n\nYou can expose TYPO3 tables as API resources with full CRUD support.\nSee [Auto-CRUD Resources Documentation](docs/Resources.md).\n\nAuto-CRUD write operations use TYPO3 `DataHandler`. If a backend user is already authenticated, the current TYPO3\nworkspace is preserved. If a dedicated write backend user is configured, TYPO3 initializes that user's default\nworkspace; set `apiResourceWriteWorkspaceId` only when writes must be forced into a specific `sys_workspace` UID.\nRaw read operations apply TYPO3 workspace visibility as well: live requests hide draft rows, workspace requests overlay\nlive rows with the current workspace version, and delete placeholders are omitted from API responses.\n\n## OpenAPI Documentation\n\nThe extension automatically generates OpenAPI 3.0 specifications. You can access Swagger UI at\n`/api/{apiId}/v{version}/docs/ui`. See [OpenAPI Documentation](docs/OpenAPI.md).\n\n## MCP Integration\n\nThe extension can expose endpoints as MCP tools through a JSON-RPC endpoint:\n\n- `POST /api/{apiId}/v{version}/mcp`\n- `GET /api/{apiId}/v{version}/mcp` for the optional Streamable HTTP SSE channel\n\nUse `api:mcp:list` to see the effective tool exposure after configuration, denylist, and endpoint-level exclusions.\nSee [MCP Documentation](docs/MCP.md).\n\n## Backend Module\n\nThe extension provides a TYPO3 Backend Module under **System \u003e API Core**.\n\n- **APIs \u0026 Versions**: Overview and Swagger UI links.\n- **Token Management**: Create and manage Opaque and Refresh tokens.\n  - Supports optional FE-user bound tokens (`user_id` mapped to `fe_users`) for per-user API key flows.\n  - Token list keeps current filter state while editing/revoking/regenerating.\n- **Endpoints**: List of all registered endpoints and their requirements, including effective MCP exposure (tool names,\n  attribute-based exclusions, and API/version mapping).\n\nThe module is available in both live and offline workspaces.\n\nSee [Authentication \u0026 Scopes - Backend](docs/AuthScopes.md#token-management-in-the-backend) for details.\n\n## Logging\n\nComprehensive logging for API requests and responses, including request tracking via a unique Request ID.\nSee [Logging Documentation](docs/Logging.md).\n\n## Multi-Tenancy\n\nEvery API request runs in a `TenantContext`, usually derived from the TYPO3 Site. Endpoints can be filtered by\ntenants using the `tenants` property in the `#[ApiRoute]` attribute.\nSee [Tenants Documentation](docs/Tenants.md).\n\n## Security \u0026 Authentication\n\nSupports multiple auth modes (`public`, `token`, `user`) and scope-based authorization.\n\n- **API Level**: Define the default `authMode` as a **string** in the `ApiRegistry`.\n- **Endpoint Level**: Override or extend the `authMode` using the `#[ApiRoute]` attribute (supports **string** or **array**, e.g., `['public', 'user']`).\n\nSee [Authentication \u0026 Scopes](docs/AuthScopes.md).\n\n### CORS\n\nCORS handling is provided by `ApiCorsMiddleware` and is enabled for API paths (`apiPathPrefix`) by default.\n\n- Origin policy is **default deny**.\n- Preflight requests (`OPTIONS` with `Access-Control-Request-Method`) are answered directly.\n- Allowed origins are configured per API via `ApiRegistry::registerApi(..., $security)`:\n\n```php\n$apiRegistry-\u003eregisterApi('partner', ['1'], [\n    'authMode' =\u003e 'user',\n    'authProviders' =\u003e ['beareropaquetokenprovider'],\n    'cors' =\u003e [\n        'allowedOrigins' =\u003e ['https://app.example.org'],\n        'allowCredentials' =\u003e true,\n    ],\n]);\n```\n\n### Known Issues \u0026 Troubleshooting\n\n#### Missing Authorization Header (Apache)\n\nIn some hosting environments (especially Apache with PHP via CGI/FastCGI), the `Authorization` header is stripped before it reaches PHP. If you experience \"Authentication required\" errors despite sending a valid token, add the following to your `.htaccess` file:\n\n```apache\nSetEnvIf Authorization \"(.*)\" HTTP_AUTHORIZATION=$1\n```\n\nThe extension includes a fallback to check for `HTTP_AUTHORIZATION` and `REDIRECT_HTTP_AUTHORIZATION`, but this server-side configuration is the most reliable fix.\n\n## Legacy Support (Migration from sg_rest)\n\nThe extension provides a bridge to support legacy `sg_rest` clients. This includes:\n\n- Middleware for mapping old URL patterns.\n- Support for `fe_users` authentication tokens.\n- Emulation of the old response format.\n\n**Note**: Legacy support is **disabled by default**. See the [Migration Guide](docs/Migration.md) for details on how to\nenable and use it.\n\n## Architectural Decisions\n\nFor information on why we chose certain technologies and patterns, see our Architectural Decision Records at docs/adr/.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdirnbauer%2Fsg_apicore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdirnbauer%2Fsg_apicore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdirnbauer%2Fsg_apicore/lists"}