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
Beschreibung von Modellteilen als formatierter Text (Rich Text)
#28708
Standard-Selektion in (Baum-)Tabellen und Grids per TL-Script berechenbar machen
#29102
Add com.top_logic.layout.react module for React/SSE integration
#29221
Automatische Bestimmung möglicher Berechtigungskonfigurationen
#29349
XML-Parse-Funktionen für TL-Script über XMLImporter
#29374
TL-Script: gzip()
#29389
Code-Completion für Variablen ($) im TL-Script-Editor
#29396
Conversation display for TL Views: object-list element, file chips, card panels
#29399
Info-Service-Meldungen: unten statt oben anzeigen und beim Überfahren mit der Maus fixieren
#29400
Introduce a first-class application "operation mode" service (OperationMode enum + ApplicationModeService)
minor
#29085
Neu einloggen bei Session Timeout anstatt Redirect zur Login-Seite
#29089
TL-Script-Funktionen log() und info() um wählbaren Meldungs-Level (INFO, WARN, ERROR) erweitern
#29195
Probleme mit HTML-Attributen und TL-Script
#29306
TL Script: dateFormat() should accept an explicit timezone to format Calendar values losslessly
#29382
Expose a public classpath-driven Workspace.getAppPaths overload
#29385
App archetype should scaffold a standard git-ignored local-credentials overlay (tl_config) by default
#29392
Transaktionsabbruch bei Nicht-2xx Response
#29398
Login-Maske: Statt "Name" besser "Benutzername"

defect

major
#29383
Dead SOCKET_APPENDER (Chainsaw, localhost:4445) in default logging config can stall logging and abort operations under load
#29384
TL-Script resetSequence/generateSequenceId build a different sequence id than SequenceDefaultProvider (suffix/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
Referenzwertige Attribute erzeugen Fehler nur bei SingleSelection
#29359
Unsinniger Tooltip bei einigen Hauptreitern
#29360
Sporadische Fehlermeldung im Log: "mainLayout" ist null.
#29361
Invalide Datenbankdefinition für Tag
#29363
Fehlende Validierung von Dialogen bei GOTOs zu Dialogen von unsichtbaren Parents
#29380
Kontextabhängige Auto-Nummerierung schlägt fehl, wenn Kontext und nummeriertes Objekt in einer Transaktion erzeugt werden
#29381
Doppelklick in Grafikkomponente funktioniert nicht zuverlässig
#29390
Teilbaum-Auswahl endet zu früh, wenn die unterste Ebene vom Ebenen-Filter nicht mitgezählt wird
#29393
URL-Routing der React-View-Schicht defekt: ForwardingReactContext delegiert getRouteManager() nicht
#29401
Bilder in einem Bild-Drop-Feld können nicht über das Browser-Kontextmenü kopiert/gespeichert werden
#29402
Baum-Selektion geht bei Aktualisierung der Ansicht (invalidate) verloren
#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, the 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 like "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 status quo and the proposed system in detail.

Migration

Model-based access rights are active by default in every application: the new SecurityConfigurationService is started by the framework and all model access through TL-Script (and the Java API 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 for any role-based user (administrators and code running in a system context bypass the checks).

An application that is updated without further action therefore keeps working for administrators, but regular users no longer see model data in TL-Script based views and TL-Script based modifications fail. Every application must supply 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 an own *.config.xml 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 for everybody. -->
<part name="myapp:Contract#secret">
<grant operation="Read"/>
</part>

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

</config> }}}

Rules:

  • operation is a BoundCommandGroup: the built-in groups Read, Write, Create, Delete, plus any custom command group of the application.
  • Type, module and inherited grants are additive (union of the roles). Attribute grants (<part>) restrict: the user needs the type-level right and one of the roles of the attribute grant. Singleton grants are standalone.
  • inherit="true" propagates a grant to sub-types (for a module grant: also to sub-types 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 is 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 the empty value when the user must not read the attribute on that object.
  • Modifying (set, add, remove), creating (new) and deleting (delete) fail with a TopLogicException when the corresponding right is missing.
  • TL-Script based model builders filter their result by read access: ListModelByExpression, ModelProviderByExpression, TreeModelByExpression, SelectionUpdaterByExpression, TableContentProvider, ForeignObjectsTemplateProvider and the script console.
  • copy() and the BPE process instantiation check the CREATE right.
  • Not checked: computed (derived) attributes - they are evaluated with definer's rights -, constraints, internal framework scripts, code in a system context, and administrators.
  • all() and kbQuery() deliberately return unfiltered results; the caller filters (in TL-Script with filterSecurity(), in Java with SearchExpression.filterSecurity(...)).
  • A script that is 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 disabled security (see section 7).
3. Security parents: `getSecurityParent()` is replaced

AbstractBoundWrapper.getSecurityParent() is final now 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 a DAG now),
  • or - preferred - configure the parent declaratively at 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> }}}

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

4. Rule ids

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

5. New framework configuration for accounts
  • A new role PersonalProfile is declared (InitialRolesManager) together with a role rule that grants it to every user on their own account, plus read/write grants for tl.accounts:Person and the matching contact configuration in com.top_logic.contact. This is what lets a user see and edit their own account and contact. Applications that already define a role of that name must rename theirs.
  • Writing tl.accounts:Person#admin is denied for everybody (grant without roles), i.e. the flag can no longer be set through model access (TL-Script, REST); it is changed through the account administration only.
6. Custom Java code
  • A QueryExecutor applies security by default. Internal queries that must see all objects regardless of the current user have to call QueryExecutor.disableSecurity() explicitly.
  • Custom TL-Script functions implemented in Java that read or write the model should extend GenericMethodWithSecurity / SearchExpressionWithSecurity and evaluate usesSecurity() (checking with ModelAccessRights.getInstance()), so that they can be switched off together with the surrounding expression. Plain GenericMethod implementations keep compiling, 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 no longer compiles 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> becomes a <config service-class="..."><instance class="..." some-option="..."/></config> entry; a configurable implementation class (ConfiguredRuntimeModule class property, RuntimeModuleProxy) is the class attribute of <instance>.

Further 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 offer 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 is removed (the optimizer is always on); delete it from an application's ModelBasedSearch service configuration, otherwise the configuration fails with an unknown property.
  • RoleComputation(StorageAccessManager) became RoleComputation(Person, StorageAccessManager); ElementAccessManager gained 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
  • EN
  • Login