Write privilege model 

Write operations (create, update, delete) pass through a write privilege model that sits between the access check (Security) and the TYPO3 DataHandler. It decides under which identity a write executes, enforces a table-level policy that no resource configuration can weaken, and records every mutation with the acting user.

Write modes 

Each resource has a write mode, configured as general.writeMode:

Mode Behaviour
acting_user Default. The DataHandler runs under the identity of the real authenticated user (frontend or backend), so TYPO3's own access control applies and the actor is preserved for auditing.
system_admin Opt-in. The DataHandler runs under a synthetic backend administrator (uid=0, admin=1) with no user identity.
'general' => [
    'table'        => 'tx_myext_domain_model_internal',
    'resourceName' => 'internal-records',
    'resourceType' => 'InternalRecord',
    'operations'   => ['list', 'create'],
    'writeMode'    => 'system_admin',   // default: 'acting_user'
],
Copied!

Actor resolution 

The acting user is resolved from the request in a fixed order:

  1. Frontend user — a frontend.user request attribute with a non-empty uid yields actorType = 'fe_user'.
  2. Backend user — an authenticated $GLOBALS['BE_USER'] yields actorType = 'be_user'.
  3. No user — falls back to actorType = 'system', and system mode is forced regardless of the configured writeMode.

In acting_user mode the DataHandler's internal username encodes the resolved actor, so TYPO3's own sys_history and log entries stay traceable to a real account:

_tca_api[fe_user:42:johndoe]
_tca_api[be_user:1:admin]
Copied!

Table access control 

A table-level policy is enforced on every write, in both write modes, before the DataHandler is reached. A blocked table returns 403 Forbidden.

Built-in deny list 

These tables are always blocked, and no configuration can unblock them:

Table Reason
be_users Backend user accounts and credentials
be_groups Backend permission groups
be_sessions Active backend sessions
fe_sessions Active frontend sessions
sys_filemounts File system mount points
sys_be_shortcuts Backend user shortcuts
sys_action System actions
sys_log System log

Narrowing or extending the policy 

The built-in list can be extended, never reduced. Configure \MaikSchneider\TcaApi\Security\TableAccessControl in your extension's Configuration/Services.yaml:

services:
  MaikSchneider\TcaApi\Security\TableAccessControl:
    arguments:
      # When non-empty, ONLY these tables are writable
      $allowList:
        - tx_myext_domain_model_article
        - tx_myext_domain_model_comment
      # Denied in addition to the built-in list
      $denyList:
        - pages
        - tt_content
Copied!

An empty $allowList (the default) means "every table that is not denied". Deny always wins: a table named in both lists is denied.

Audit logging 

Every write is logged through TYPO3's PSR-3 logging framework, so it can be routed to any configured handler.

A permitted write is logged at info level as TCA API write operation:

operation:      create
table:          tx_myext_domain_model_article
uid:            NEW_primary
actor_type:     fe_user
actor_uid:      42
actor_username: johndoe
write_mode:     acting_user
Copied!

A write refused by the table policy is logged at warning level as TCA API write denied, with the same actor context plus a reason:

operation:      write
table:          be_users
actor_type:     fe_user
actor_uid:      42
actor_username: johndoe
write_mode:     acting_user
reason:         Table blocked by access control policy
Copied!

The uid of a create is the DataHandler placeholder (NEW_…) rather than the final record uid, because the entry is written before persistence.