enhancement
major
minor
defect
critical
major
minor
major
#30255
tl-ai-core: agent turn rolled back with "Create on objects of type ... without permission" when a tool creates a part in an object created in the same turn - remove the duplicate pre-commit guard, check initial values in TL-Script
tl-ai-core 8.0.0-alpha12.819, application E-Home (haumacher/ehome #127).
Problem
An agent tool (DATA_WRITE, run in the turn's transaction) creates an object and parts in it in one call: a building with a floor, a communication object's first connection (a new connector holding a new connection), a duplicated device with its parameter settings. The turn is rolled back by the pre-commit guard:
Create on objects of type 'ehome.building:Floor' ... without permission
The account (role ehome.Installer) may create both types; the same operations succeed from the view layer.
Cause
ModelSecurityPreCommitGuard.checkCreation asks canCreate(type, container) in the committed view (withoutModifications). A container created in the same turn does not exist in that view, and SecurityConfigurationService.isAllowedCreate decides an invalid context as deleted before it reaches its own rule for a context built in the current transaction ("uncommitted context -> allowed").
The guard itself is a duplicate: it re-asks, after the fact and reconstructed from the transaction's change set, the questions the engine already asks while the tools write. TL-Script new(), set(), add(), remove() and delete() check the user's rights by default (WithSecurityCheck), so ChangeDataTool scripts and TL-Script tools of the application are checked when they run; remote MCP tools write into their own system, outside the turn's transaction. The guard's own view switching (committed view for deleted objects, transaction view for new ones) is what produced the wrong refusal.
The only question the guard asked that nothing else asks is the right to set an initial value of a new object (#683): TL-Script set() asks ModelAccessRights.isAllowed(..., WRITE), which allows everything on an object not yet committed, so a script run with the user's rights may set an attribute of a new object that the create dialogs would not let the user set.
Solution
- The pre-commit guard is removed from tl-ai-core (PreCommitGuard, ModelSecurityPreCommitGuard, its calls in AgentLoop and in the MCP server's McpToolAdapter, its tests and its developer article). An agent turn commits what its tools wrote under the user's rights; the tools' own checks (Java tools via ModelSecurity, TL-Script via the engine) are the security of a write. ToolChangeSet stays, it is the basis of the change report of the write tools.
- Update.checkWritePermission (the write check of TL-Script and of the view layer's save paths) asks ModelAccessRights.isAllowedInitial for an object not yet committed, the question the create dialogs ask, instead of isAllowed. A script run with the user's rights can no longer set an initial value the user may not set.
Migration
- An application script that runs with security (the default) and sets an attribute with an attribute-level WRITE grant on an object created in the same transaction - e.g. a "created by" field the user may not edit - is now refused for a user without that grant. Either grant the role the right on the attribute or run that script without security.
- Workarounds for the wrong refusal of the pre-commit guard (e.g. a SecurityContextFactory answering canCreate with yes for a container created in the same turn) can be removed.
- Die Klassen com.top_logic.tl.ai.core.security.PreCommitGuard und ModelSecurityPreCommitGuard entfallen. Eigener Code, der sie verwendet oder implementiert, entfernt diese Verwendungen; die Rechte eines Schreibzugriffs prüfen die Werkzeuge selbst (Java-Werkzeuge über ModelSecurity, TL-Script über die Engine).