TopLogic - the automated application engine
  • Releases
  • Dokumentation
  • Github
  • Discord
  1. Home
  2. Releases
  3. TL_8.0.0-alpha7
  4. #29088

8.0.0-alpha7
TopLogic Release

2026-07-30

enhancement

critical
#29088
Model-based access rights
#29108
Lightweight UI definition layer (TL Views) based on React UI components
major
#28694
Description of model parts as formatted text (rich text)
#28708
Enable Standard Selection in (Tree) Tables and Grids via TL Script
#29102
Add com.top_logic.layout.react module for React/SSE integration
#29221
Automatic determination of possible authorization configurations
#29349
XML Parsing Functions for TL-Script via XMLImporter
#29374
TL Script: gzip()
#29389
Code Completion for Variables ($) in the TL Script Editor
#29396
Conversation display for TL Views: object list element, file chips, card panels
#29399
Info Service Notifications: Display at the bottom instead of the top, and keep them in place when hovering over them with the mouse
#29400
Introduce a first-class "operation mode" service for applications (OperationMode enum + ApplicationModeService)
minor
#29085
Re-login on session timeout instead of redirect to login page
#29089
Extend the TL Script functions log() and info() to include selectable message levels (INFO, WARN, ERROR)
#29195
Problems with HTML attributes and TL script
#29306
TL Script: dateFormat() should accept an explicit timezone to format Calendar values losslessly
#29382
Expose a public, classpath-driven overload of `Workspace.getAppPaths`
#29385
The app archetype should automatically generate a standard git-ignored local-credentials overlay (tl_config) by default
#29392
Transaction Abort on Non-2xx Response
#29398
Login Form: Use "Username" Instead of "Name"

defect

major
#29383
A dead SOCKET_APPENDER (Chainsaw, localhost:4445) in the default logging configuration can cause logging to stall and operations to abort under heavy load
#29384
The TL-Script functions `resetSequence` and `generateSequenceId` generate a different sequence ID than `SequenceDefaultProvider` (in terms of suffix and context order), so they cannot reset a provider-managed sequence with a dynamic context
#29394
Editable tables in the React UI: Generalized row-set bindings for tabular editing in forms
#29410
Attribut filename der Structured-Text-Bildablage case-sensitive (binär) speichern
#29419
Understandable save failures and form validation feedback in the React view layer
minor
#28816
Reference value attributes only generate errors with SingleSelection
#29359
Inappropriate tooltips on some main tabs
#29360
Occasional error message in the log: "mainLayout" is null.
#29361
Invalid database definition for tag
#29363
Missing validation of dialogs in GOTO statements to dialogs of invisible parents
#29380
Context-sensitive auto-numbering fails if the context and the numbered object are created within a single transaction
#29381
Double-clicking in a graphic component does not work reliably
#29390
Subtree selection ends too early if the lowest level is not included in the level filter
#29393
URL routing in the React view layer is broken: ForwardingReactContext does not delegate getRouteManager()
#29401
Images in an image drop zone cannot be copied or saved using the browser's context menu
#29402
Tree selection is lost when the view is refreshed (invalidated)
#29412
Flaky TestDynamicComponentService.testIncrementalUpdates: asserts on asynchronous WatchService event after a fixed 10ms sleep
#29416
Anzeige des Änderungslogs schlägt fehl, wenn parallel Änderungen committet werden
#29420
FlowDiagram: Fehlerfall im row-wise Sub-Grid: subGridCols=2 und subGridStartCol=1
#29426
FlowDiagram: Text in PDF-eingebettetem Diagramm ist nicht selektierbar

task

major
#29407
Security-Scan: npm-Abhängigkeiten der React-Module aktualisieren
#29408
Security-Scan: httpcore5 anheben; pdfbox-/azure-Findings bewerten
minor
#29415
Slim down the repository CLAUDE.md and consolidate developer guidance into skills and FAQ articles
enhancement

critical

#29088

Model-based access rights

MigrationModelAccessRightsSecurity

Currently, access rights administration in TopLogic is view-based: the PersBoundComp configuration defines which roles can execute which command groups in which views (CompoundSecurityLayout). While role assignments on model instances are already model-based, the final permission mapping (command group → roles) is tied to the layout structure.

For non-UI access paths (AI assistants, REST APIs, batch jobs, TL-Script), there is no natural view context to evaluate. This makes it impossible to directly answer questions such as “which users can read/update/create which model elements.”

This ticket tracks the design and implementation of a model-based access rights definition that:

  • Defines access rules (operation → roles) on model elements (types, attributes, modules) rather than views
  • Provides a ModelAccessRights API for programmatic access checks
  • Allows views to derive their permissions from model-level rules
  • Maintains backward compatibility with the existing view-based configuration

The specification document model-based-access-rights.md describes the current state and the proposed system in detail.

Migration

Model-based access rights are enabled by default in every application: the new SecurityConfigurationService is started by the framework, and all model access via TL-Script (and the Java API built on top of it) is checked against its configuration. The configuration is deny-by-default: a type without a grant for a command group is not accessible to any role-based user (administrators and code running in a system context bypass the checks).

An application that is updated without further action therefore continues to work for administrators, but regular users no longer see model data in TL-Script-based views, and TL-Script-based modifications fail. Every application must provide a <security-config> for its model.

1. Configure the access rights of the application model

Add a service configuration for com.top_logic.model.security.SecurityConfigurationService (e.g., as a separate *.config.xml file registered in the application’s metaConf.txt):

{{{#!xml <config service-class="com.top_logic.model.security.SecurityConfigurationService">

<instance>
<security-config>
<-- Baseline for all types of a module. -->
<module name="myapp">
<grant operation="Read" roles="Viewer, Editor, Manager" inherit="true"/>
<grant operation="Write" roles="Editor, Manager" inherit="true"/>
<grant operation="Create" roles="Editor, Manager" inherit="true"/>
<grant operation="Delete" roles="Manager" inherit="true"/>
</module>

<-- Refinement for a single type, e.g., a custom command group. -->
<class name="myapp:Order">
<grant operation="Approve" roles="Manager, Approver"/>
</class>

<-- Attribute-level restriction: narrows the type-level grant. -->
<part name="myapp:Customer#salary">
<grant operation="Read" roles="Manager"/>
<grant operation="Write" roles="Manager"/>
</part>

<-- A grant without roles denies the operation to everyone. -->
<part name="myapp:Contract#secret">
<grant operation="Read"/>
</part>

<-- Views without a domain type: use a module singleton as the security object. -->
<singleton name="myapp:AdminPanel">
<grant operation="Read" roles="Admin"/>
<grant operation="Write" roles="Admin"/>
</singleton>
</security-config>
</instance>

</config> }}}

Rules:

  • An operation is a BoundCommandGroup: the built-in groups Read, Write, Create, Delete, plus any custom command group defined by the application.
  • Type, module, and inherited grants are additive (union of the roles). Attribute grants (<part>) impose a restriction: the user must have the type-level right and one of the roles specified in the attribute grant. Singleton grants are standalone.
  • inherit="true" propagates a grant to subtypes (for a module grant: also to subtypes defined in other modules).
  • The referenced roles must exist in the database (e.g., declared via InitialRolesManager), and the roles are still assigned per instance as before (hasRole records, role rules, security parent chain). A role name that cannot be resolved is reported as a configuration error at startup.
  • The starting point for the rewrite is the existing role profile of the views (PersBoundComp): the roles that were configured there for a command group become the roles of the corresponding grant on the displayed type. PersBoundComp itself remains unchanged and still governs the classic layout security.

A complete example is the configuration of the demo application in com.top_logic.demo/src/main/webapp/WEB-INF/conf/com.top_logic.model.security.SecurityConfigurationService.config.xml; the full concept is documented in specs/model-based-access-rights.md.

2. Where the new checks apply
  • Reading an attribute in TL-Script ($obj.get(...)) returns an empty value if the user is not authorized to read that attribute on the object.
  • Modifying (set, add, remove), creating (new), and deleting (delete) operations result in a TopLogicException if the corresponding right is missing.
  • TL-Script-based model builders filter their results based on read access: ListModelByExpression, ModelProviderByExpression, TreeModelByExpression, SelectionUpdaterByExpression, TableContentProvider, ForeignObjectsTemplateProvider, and the script console.
  • The `copy() ` method and the BPE process instantiation check the `CREATE` right.
  • Not checked: computed (derived) attributes—they are evaluated using the definer’s rights—constraints, internal framework scripts, code in a system context, and administrators.
  • `all() ` and `kbQuery()` deliberately return unfiltered results; the caller performs the filtering (in TL-Script using `filterSecurity()`, in Java using `SearchExpression.filterSecurity(...)`).
  • A script executed without a logged-in user has no rights at all. Background jobs (tasks, batch processing) must run in a system context (ThreadContext.inSystemContext(...)) or use an executor with security disabled (see section 7).
3. Security parents: `getSecurityParent()` has been replaced

AbstractBoundWrapper.getSecurityParent() is now final and throws an UnsupportedOperationException. Applications that override the single-valued security parent must be adapted:

  • Either override ` BoundObject.getSecurityParents() ` (returning a collection—the security hierarchy is now a DAG),
  • or—preferred—configure the parent declaratively in the AccessManager:

{{{#!xml <config service-class="com.top_logic.tool.boundsec.manager.AccessManager">

<instance>
<security-parents>
<rule id="ProjectForMilestone"
inherit="true"
meta-element="myapp:Milestone"
>
<step attribute="myapp:Milestone#project"/>
</rule>
<rule id="SecRootForProject"
inherit="true"
meta-element="myapp:Project"
>
<singleton module="SecurityStructure"/>
</rule>
</security-parents>
</instance>

</config> }}}

Behavior change: the global security root is now used only as a fallback. As soon as security parents are configured for a type, the root is no longer added automatically. A type that requires the root in its parent chain must explicitly specify it using the new <singleton> path element (as in the example above). Otherwise, roles granted to the security root are no longer inherited by those objects.

4. Rule IDs

Role rules and security parent rules require an ID. Existing configurations are covered by the migration in #29221 (AddRoleRuleId); rules added manually need their own ID.

5. New framework configuration for accounts
  • A new role, `PersonalProfile`, is declared (InitialRolesManager) along with a role rule that grants it to every user on their own account, plus read/write permissions for `tl.accounts:Person` and the corresponding contact configuration in `com.top_logic.contact`. This is what allows a user to view and edit their own account and contact information. Applications that already define a role with that name must rename theirs.
  • Writing to tl.accounts:Person#admin is denied for everyone (grant without roles), i.e., the flag can no longer be set via model access (TL-Script, REST); it can only be changed through account administration.
6. Custom Java Code
  • A QueryExecutor applies security by default. Internal queries that must access all objects regardless of the current user must explicitly call QueryExecutor.disableSecurity().
  • Custom TL-Script functions implemented in Java that read or write the model should extend ` GenericMethodWithSecurity ` or ` SearchExpressionWithSecurity ` and evaluate `usesSecurity() ` (checking with `ModelAccessRights.getInstance()`), so that they can be disabled along with the surrounding expression. Plain GenericMethod implementations continue to compile, but they bypass model security.
  • Programmatic access checks are available through the ModelAccessRights service (isAllowed, isReadAllowed, isAllowedCreate, getAllowedRoles, getAccessibleTypes); the corresponding TL-Script functions are canRead, canWrite, canDelete, canCreate, canReadAttribute, canWriteAttribute, canExecute, and filterSecurity.
7. Removed legacy module system and other Java API changes

The rework removed the legacy, properties-based service module family from com.top_logic.basic.module: RuntimeModule, ConfiguredRuntimeModule, MultiRuntimeModule, RuntimeModuleProxy, ServiceManager, DefaultServiceManager, and the constructors ManagedClass(Properties) / ManagedClass(IterableConfiguration). An application service that still uses them will no longer compile and must be converted to typed configuration:

{{{#!java @ServiceDependencies({ OtherService.Module.class }) // replaces getDependencies() public class MyService extends ConfiguredManagedClass<MyService.Config> {

public interface Config extends ConfiguredManagedClass.Config<MyService> {
@Name("some-option") String getSomeOption(); // one typed getter per former property
}
@CalledByReflection
public MyService(InstantiationContext context, Config config) { super(context, config); }
public static final class Module extends TypedRuntimeModule<MyService> {
public static final Module INSTANCE = new Module();
@Override public Class<MyService> getImplementation() { return MyService.class; }
}

} }}}

The former properties <section> become a <config service-class="..."><instance class="..." some-option="..."/></config> entry; a configurable implementation class (ConfiguredRuntimeModule class property, RuntimeModuleProxy) is the class attribute of <instance>.

Additional changes made by this ticket:

  • The no-argument / Properties constructors of DataManager, FileSystemCache, FlexDataManagerFactory, EncryptedFlexDataManagerFactory, InitialDataSetupService, and CommandApprovalService are replaced by (InstantiationContext, Config) constructors; subclasses must implement them.
  • BoundChecker#getRolesForCommandGroup(...) must return a non-null collection (Collections.emptySet() instead of null); the default allow(...) implementation no longer tolerates null.
  • The ModelBasedSearch configuration property `disable-optimizations ` has been removed (the optimizer is always enabled); delete it from an application’s ModelBasedSearch service configuration, otherwise the configuration will fail with an “unknown property” error.
  • RoleComputation(StorageAccessManager) has been renamed to RoleComputation(Person, StorageAccessManager); ElementAccessManager now includes the hooks getSecurityParents(BoundObject) and canHaveRole(TLClass, BoundedRole) for application access managers.
  • AbstractCssClassUpdate.writeCssClassContent(...) is public abstract (a protected override no longer compiles).
  • Get Started
  • Github
  • Discord
  • Das Unternehmen hinter TopLogic
  • Softwareentwicklung heute
  • Kontakt

© Copyright – Business Operation Systems GmbH

  • top-logic.com
  • Nutzungsbedingungen
  • Impressum
  • Rechtlicher Hinweis
  • Datenschutz
  • DE
  • Login