diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js
index 86fd5981..14691e7e 100644
--- a/src/.vuepress/config.js
+++ b/src/.vuepress/config.js
@@ -209,6 +209,7 @@ module.exports = config({
children: [
['applications/modules/bootstrap/tags', 'Tags'],
['applications/modules/bootstrap/dynamic-attributes', 'Dynamic Attributes'],
+ ['applications/modules/bootstrap/data-security-model', 'Data Security Model'],
{
title: 'Data',
collapsable: true,
@@ -217,7 +218,7 @@ module.exports = config({
['applications/modules/bootstrap/data/data-checks', 'Checks'],
['applications/modules/bootstrap/data/data-transformations', 'Transformations']
]
- }
+ },
]
},
['preparing-content', 'Commerce Start'],
diff --git a/src/en/developer-guide/applications/modules/bootstrap/data-security-model.md b/src/en/developer-guide/applications/modules/bootstrap/data-security-model.md
new file mode 100644
index 00000000..2478b768
--- /dev/null
+++ b/src/en/developer-guide/applications/modules/bootstrap/data-security-model.md
@@ -0,0 +1,198 @@
+---
+title: Data Security Model
+tagline: Centralized and flexible control over portal permissions.
+author: Safija Hubljar
+---
+
+## Introduction
+
+The Portal Data Security Model gives you a flexible way to manage portal permissions across all entities. It relies on a combination of shared default rules and optional overrides, so you can enforce consistent access control without duplicating rules or hardcoding logic.
+
+At the core, the model uses two main configuration tables:
+
+* **Permission Level Defaults**
+* **Entity Auth Template**
+
+---
+
+### Permission Level Defaults
+
+This table sets default access rules that apply to all entities. The `talxis_permissionleveldefaults` are provided by TALXIS and are based on Business Unit security.
+
+It’s mainly used in situations when you want the same rules applied across multiple entities
+
+| Display Name | Logical Name | Description |
+| ------------------------ | --------------------------------------- | ------------------------------- |
+| OData Filter | `talxis_odatafilter` | Custom OData filter. |
+| FetchXML | `talxis_fetchxml` | FetchXML query expression. |
+| Power Fx | `talxis_powerfx` | Power Fx formula expression. |
+| Preferred Query Language | `talxis_preferredquerylanguagetypecode` | Preferred query language. |
+| Permission Level | `talxis_permissionlevel` | Specifies the permission level. |
+
+---
+
+### Entity Auth Template
+
+The Entity Auth Template is used for entities that:
+
+* Require entity-specific security rules
+
+**Key features:**
+
+* Handles both default and override queries
+* Lets you control permissions at a fine-grained level per entity
+* Supports custom filtering logic when defaults are not enough
+
+| Display Name | Logical Name | Description |
+| ------------------------- | ---------------------------------------- | ------------------------------------------------- |
+| Entity Set Name | `talxis_entitysetname` | Name of the entity set. |
+| Entity Logical Name | `talxis_entitylogicalname` | Logical name of the entity. |
+| Entity Description | `talxis_entitydescription` | Explanation of the entity. |
+| Allowed Permission Levels | `talxis_allowedpermissionlevelstypecode` | Which permission levels are allowed. |
+| Owner Principal Id | `talxis_ownerprincipalid` | Unique ID of the record owner. |
+| Modified By Principal Id | `talxis_modifiedbyprincipalid` | ID of the user who last modified the record. |
+| Default Read | `talxis_default_read` | Default read permission. |
+| Default Create | `talxis_default_create` | Default create behavior. |
+| Default Write | `talxis_default_write` | Default write behavior. |
+| Default Delete | `talxis_default_delete` | Default delete behavior. |
+| Default Select | `talxis_default_select` | Attributes selected by default (comma-separated). |
+| Override None OData | `talxis_override_none_odata` | No OData override applied. |
+| Override None Power Fx | `talxis_override_none_powerfx` | No Power Fx override applied. |
+| Override None FetchXML | `talxis_override_none_fetchxml` | No FetchXML override applied. |
+| Override Basic OData | `talxis_override_basic_odata` | Basic OData override applied. |
+| Override Basic Power Fx | `talxis_override_basic_powerfx` | Basic Power Fx override applied. |
+| Override Basic FetchXML | `talxis_override_basic_fetchxml` | Basic FetchXML override applied. |
+| Override Local OData | `talxis_override_local_odata` | Local OData override applied. |
+| Override Local Power Fx | `talxis_override_local_powerfx` | Local Power Fx override applied. |
+| Override Local FetchXML | `talxis_override_local_fetchxml` | Local FetchXML override applied. |
+| Override Deep OData | `talxis_override_deep_odata` | Deep OData override applied. |
+| Override Deep Power Fx | `talxis_override_deep_powerfx` | Deep Power Fx override applied. |
+| Override Deep FetchXML | `talxis_override_deep_fetchxml` | Deep FetchXML override applied. |
+| Override Global OData | `talxis_override_global_odata` | Global OData override applied. |
+| Override Global Power Fx | `talxis_override_global_powerfx` | Global Power Fx override applied. |
+| Override Global FetchXML | `talxis_override_global_fetchxml` | Global FetchXML override applied. |
+
+---
+
+### Permission Level optionset (talxis_permissionleveltypecode)
+
+Supported types:
+
+| Label | Value |
+|-----------------------------------|-------------------|
+| None | 742070000 |
+| Basic | 742070001 |
+| Local | 742070002 |
+| Deep | 742070003 |
+| Global | 742070004 |
+
+### Preferred Query Language optionset (talxis_preferredquerylanguagetypecode)
+
+Supported types:
+
+| Label | Value |
+|-----------------------------------|-------------------|
+| Odata | 742070000 |
+| FetchXML | 742070001 |
+
+### Preconfigured Authorization Context Variables (talxis_configuration_authcontextvariable)
+
+| Variable | Description | Use Case |
+| ------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------|
+| `childbusinessunits` | First level of child business units of the user’s business units | Used to filter subordinate business units of the current user. |
+| `mybusinessunits` | Security Team of type business units, where user belongs to via child teams (security teams) | Retrieves business units the user has access to through security teams. |
+| `mysecurityteamsarray` | All security teams the current user belongs to | Retrieves all security teams of the user. |
+
+### Preconfigured Permission Level Defaults (talxis_permissionleveldefaults)
+
+| Permission Level | OData Filter | FetchXML | Power Fx | Use Case |
+|-----------------|-------------|----------|----------|----------|
+| None | `createdon eq null` | `` | `false` | Default – no access to records |
+| Basic | `talxis_accessprincipalid eq '{ { AuthorizationContextVariables.talxis_accessprincipalid } }'` | `` | `talxis_accessprincipalid = AuthorizationContextVariables.talxis_accessprincipalid` | Access to records owned by the current user |
+| Local | `Microsoft.Dynamics.CRM.In(PropertyName='owningbusinessunit',PropertyValues='{ { AuthorizationContextVariables.mybusinessunits } }')` | `{ { AuthorizationContextVariables.mybusinessunits_fetchxml } }` | `owningbusinessunit in AuthorizationContextVariables.mybusinessunits` | Access to records within the user’s business units |
+| Deep | `Microsoft.Dynamics.CRM.In(PropertyName='owningbusinessunit',PropertyValues='{ { AuthorizationContextVariables.mybusinessunits } }') or Microsoft.Dynamics.CRM.In(PropertyName='owningbusinessunit',PropertyValues='{ { AuthorizationContextVariables.childbusinessunits } }')` | `{ { AuthorizationContextVariables.mybusinessunits_fetchxml } }{ { AuthorizationContextVariables.childbusinessunits_fetchxml } }` | `owningbusinessunit in AuthorizationContextVariables.mybusinessunits || owningbusinessunit in AuthorizationContextVariables.childbusinessunits` | Access to records within the user’s business units and their child units |
+| Global | `*` | `*` | `true` | Full access – for administrators and superusers |
+
+### Expected User Roles
+
+The following outlines which roles are expected to configure different parts of the security model based on required expertise:
+
+**Developers**:`talxis_permissionleveldefaults` and `talxis_entityauthtemplate` should be configured by developers, as they require knowledge of the querying languages. Any configuration allowed with `talxis_advancedmode=true` should also be handled by developers, due to the same level of technical expertise required.
+
+**Customer/Admins/Consultants**:`talxis_configuration_authruleset`,`talxis_configuration_authretrievefilter`, and `talxis_configuration_authwritecondition` can be managed by customer admins or consultants, mainly by working with `talxis_permissionleveltypecode`.
+
+### Best Practices and Considerations
+
+When setting up filters using FetchXML, OData, or Power Fx, keep these guidelines in mind:
+
+1. **Use explicit filters, avoid wildcards**
+
+ * Don’t use `*` in EntitySetName or filters unless absolutely necessary.
+ * Wildcards bypass detailed permission controls and can create serious security risks.
+
+```xml
+
+
+
+
+```
+
+2. Filter Language and Scope
+
+- OData filters are usually sufficient for most scenarios and perform better than FetchXML for simple queries.
+
+- FetchXML filters are used to query and filter data using the full set of FetchXML functionality
+
+- Power Fx is used to filter create, update, and delete requests.
+
+Example OData filter
+
+```text
+contactid eq '{{ AuthorizationContextVariables.talxis_currentuser_contactid }}'
+```
+
+Equivalent FetchXML filter:
+
+```xml
+
+```
+
+3. Unsupported Scenarios
+
+- Nested queries retrieved via $expand or link-entity do not enforce permissions on child entities, only the top-level entity respects the filter rules.
+
+- Some operators, such as `in` on link-entities, are not supported and should be avoided.
+
+- Converting complex FetchXML to OData is not always reliable, always manually verify results.
+
+4. Testing and Validation
+
+- Always manually validate filters after defining them.
+
+- Test filters with multiple users having different permission levels to ensure they enforce security correctly.
+
+- Use both OData and FetchXML overrides in a sandbox environment before deploying to production.
+
+Test example scenario:
+
+- User A: Should only see accounts they own
+
+- User B: Should see all accounts created after 2024-01-01
+
+- Verify that OData and FetchXML overrides return expected records for each user.
+
+5. Recommended Override Usage
+
+- Use the override levels (None, Basic, Local, Deep, Global) to control the scope and priority of your filter rules:
+
+ - **None** – No OData override applied
+ - **Basic** – Access to owned records only
+ - **Local** – Access to business unit records
+ - **Deep** – Access to business unit records and all child business unit records
+ - **Global** – Global access
+
+- Start with OData overrides for simplicity and performance.
+
+### Rules Caching
+
+Rules are cached for 15 minutes at the backend. If you need them refreshed in an emergency situation, a backend app service restart is required.