# High level definition

General append strategy is folder based

📁 Parent folder / dossier        <- Owner (full access)
  📁 Sub folder / dossier         <- Owner (full access) + Luca (Read access)
    🧾 Document                   <- Owner (full access) + Luca (Read access)
    🧾 Document                   <- Owner (full access) + Luca (Read access) + Oliver (Read access)
🧾 Document                       <- Owner (full access)

By default, permissions shall be assigned to the folders, documents inherit permissions from their parent folder.​ Sub folder by default inherits permissions from the direct parent folder.​ Document by default inherits permissions from the direct parent folder.​ Subfolders can add permissions in addition to those inherited from the direct parent folder.​ Document can add permissions in addition to those inherited from the direct parent folder

Internal dossier structure

🏢 Tenant - Organization A
  🗀 Root Folder
    🗀 User A Folder
      🗀 Session - 1 Folder
      🗀 Session - 2 Folder
      📁 Juris Case M. Smith
        📁 Evidence
    🗀 User B Folder

🏢 Tenant – Organization B
  🗀 Root Folder
  ...

🗀 Hidden Folder (type: root | user | session) – Entirely managed by the system.​ 📁 User visible Folder (type: visible) – Managed by users.​

Folder Lifetime​:

Root Folder (type=root)​ -> Lives as long as the Tenant exist​

User Folder (type=user)​ -> Lives as long as the User exist​

Session Folder (type=session)​ -> Lives as long as the Session exist​

Juris Case Folder (type=visible)​ -> Lives as long as the user doesn't delete it​

Evidence (type=visible) -> Lives as long as the user doesn't delete it​

Override feature

Allow breaking inheritance when needed:​ e.g. confidential document inside a shared folder

📁 Parent folder / dossier
  📁 Sub folder / dossier
    🧾 Document
    🧾🔐 Document
  📁🔐 Protected folder
    🧾 Document (only inherits permissions from the direct parent folder)

🔐Protected Folder or Document ​

Ignore all previous permissions and grant access only to the user who created the document or folder, along with the document or folder own permissions.​ ​ "Protected" means:​ - Inheritance from all ancestors is stopped​ - Only the resource's own permissions apply ​ - Document Super admin bypass still applies - The acting group must hold SHARING permission over the resource to protect / unprotect it.

PERMISSIONS

Permission Documents Folders Meaning
READ X X View/open document or folder
SHARING X X Manage permissions over the dossier and document (sharing)
DELETE X X Delete document or folder
ADD X Permission to add documents in the folder. Permission to create a new folder
UPDATE X X Update folder information (e.g., dossier's name). Note: No need for UPDATE on a document unless versioning is implemented
OWNERSHIP (X) X Modify the owner of a folder. Note: Moves the folder into a folder belonging to the user performing the action (default: user's hidden folder). To change ownership of a document or folder, the user must move it to one of their folders, breaking inheritance from the previous location

ROLES

Role READ SHARING DELETE ADD UPDATE OWNERSHIP
SUPER ADMIN X X X X X X
OWNER X X X X X X
ADMIN X X X X X
MANAGER X X X X
VIEWER X

The DOCUMENT SUPER ADMIN role grants access to all documents and folders in the tenant, whether the entity is protected or not.​

The tenant group is a standard group identified by holding the system tenant-admin capability, connected through the existing (Group)-[:HAS_ROLE]->(:UserRole)-[:HAS_CAPABILITY]->(:UserCapability:SystemAcl {id: 'tenant-admin'}) chain. There is exactly one tenant group per tenant, created at bootstrap. It has no [:GRANT:<PERMISSION>] relationships on any resource — it bypasses the permission system entirely based on the capability lookup.

Note on role types: The Roles table above describes ACL Roles — in-memory abstractions that bundle permissions (OWNER, ADMIN, MANAGER, etc.). These are never stored as Neo4j nodes. The (Group)-[:HAS_ROLE]->(:UserRole)-[:HAS_CAPABILITY]->(:Capability) graph pattern describes a separate System/Tenant Role mechanism used exclusively to identify special system groups (e.g. the tenant group). The two role concepts are independent.

ACL Roles are assigned to groups.

Deletion & Restore

Exception — Session resources are directly purged (no retention): When a Session ends, its Session Folder and all resources it contains (documents and sub-folders) are immediately and permanently deleted. No recovery window applies.

Restrictions

What about cross tenant access?​

No access across tenants under any condition. A user must either use a separate account to access another tenant or exist as a duplicated user within that other tenant.​

Can there be multiple owners?​

No​

Can ownership be transferred without moving the entity? ​

No, ownership cannot be transferred without moving the entity. (An exception may apply for folders located in the Root Folder, since they do not belong to a specific user but to the organization. Only a document super admin create these entities)​

Technical implementation

Traceability - events that should be logged

Event Definition
Resource created
Resource moved
Resource renamed / metadata updated
Resource deleted
Resource restored
Permission granted
Permission revoked
Resource marked protected
Resource unprotected
Ownership changed
Sharing action performed
Access denied
Access granted
Super admin access used
Group membership changed
User removed from tenant

Resources In Neo4J DB

Entity Relationship Model (Transcribed from Diagram)

graph TD
    USER([👤 USER])
    GROUP([👥 GROUP])
    DOS([📁 DOS\nFolder / Dossier])
    DOC([🧾 DOC\nDocument])

    USER -- ":MEMBER_OF" --> GROUP
    GROUP -- ":OWNS" --> DOS
    GROUP -- ":GRANT:<PERMISSION>" --> DOS
    GROUP -- ":GRANT:<PERMISSION>" --> DOC
    GROUP -- ":OWNS" --> DOC
    DOS -- ":CONTAINS" --> DOS
    DOS -- ":CONTAINS" --> DOC

Entities

Entity Description
USER
GROUP
DOS Folder / Dossier
DOC Document
SESSION User session; lifecycle-binds a hidden session dossier (type=session)

Relationships

From Relationship To Description
USER :MEMBER_OF GROUP The user is a member of a group.
GROUP :OWNS DOS The group owns the dossier (folder).
GROUP :GRANT:<PERMISSION> DOS The group grants permissions on the dossier.
GROUP :GRANT:<PERMISSION> DOC The group grants permissions on the document.
GROUP :OWNS DOC The group owns the document.
DOS :CONTAINS DOS A dossier can contain another dossier (folder hierarchy).
DOS :CONTAINS DOC A dossier directly contains a document.
USER :HAS_SESSION SESSION The user has an active session.
SESSION :HAS_DOSSIER DOS Lifecycle binding: session deletion triggers immediate purge of the linked dossier (type=session) and all its contents.

Permission List

Permission
READ
SHARING
DELETE
ADD
UPDATE
OWNERSHIP

Nodes definition

Authorization namespace

Internal authorization nodes are explicitly partitioned with the SystemAcl label: User:SystemAcl, Group:SystemAcl, UserRole:SystemAcl, and UserCapability:SystemAcl. ACL membership, ownership, grant, and tenant-admin queries must match these composite labels. Imported diagram or ontology nodes may also use the generic Group label, but their Group:Entity nodes are intentionally not authorization groups and must not receive SystemAcl.

Node Attributes Definition
User Id, email, fullname, username The user's hidden system group is reached via (User)-[:MEMBER_OF]->(Group {isUserGroup:true}); the user's hidden dossier via (Group)-[:OWNS]->(Dossier {type:'user'}).
Group Id, name, isUserGroup isUserGroup = true for hidden single-user groups, managed entirely by the system. The tenant group is identified by holding the tenant-admin capability via (Group:SystemAcl)-[:HAS_ROLE]->(:UserRole:SystemAcl)-[:HAS_CAPABILITY]->(:UserCapability:SystemAcl {id: 'tenant-admin'}) — no property flag on the node.
Capability Id, localized names, hidden Application capabilities use hidden = true for system-only capabilities such as tenant-admin; hidden capabilities remain persisted and assigned but are omitted from roles management UI.
Document Id, name, isProtected, isDeleted, createdAt, updatedAt, deletedAt, deletedBy Ownership is tracked via the (Group)-[:OWNS]->(Document) relationship. Parent dossier is resolved via the (Dossier)-[:CONTAINS]->(Document) relationship.
Dossier Id, name, type (root | user | session | visible), isProtected, isDeleted, createdAt, updatedAt, deletedAt, deletedBy root: hidden root dossier of a tenant — no [:OWNS] relationship (sole exception to group-ownership). user: hidden dossier of a user. session: hidden session dossier. visible: user-created dossier. Parent dossier is resolved via the (Dossier)-[:CONTAINS]->(Dossier) relationship (null for the root dossier).
Session Id Links a user to their session dossier (type=session) via the (User)-[:HAS_SESSION]->(Session) relationship. Deletion triggers immediate purge of the dossier and all its contents.

Nodes relationship

Relationship Definition From To Note
GRANT grantedAt, grantedBy Group Document, Dossier A group has been given access to a resource. Permission is encoded in the relationship type — one typed relationship per permission (e.g. [:GRANT:READ], [:GRANT:SHARING]). Role (e.g. Manager) is a higher-level abstraction; it is not stored in the graph. Users are never granted directly.
OWNS Group Document, Dossier A group is responsible for the resource. Mandatory 1(Group) → 1(Resource). Users own resources via their hidden system group. Exception: the root dossier (type=root) has no owner group — no [:OWNS] relationship points to it. It is the sole exception to this rule.
CONTAINS Dossier Document, Dossier A dossier contains a document or a sub-dossier.
MEMBER_OF User Group
HAS_SESSION User Session A user has an active session.
HAS_DOSSIER Session Dossier Lifecycle binding: session deletion triggers immediate purge of the dossier (type=session) and all its contents.

Vector search – search first

Graph DB = Source of truth for permission​ Vector DB = Store embeddings + document IDs​ Step 1: Run vector search to get candidate documents​

Step 2: Filter candidates using access control​

Step 3: Return only accessible document ​ ​

What if top 100 results contains only unauthorized documents?​ → Fetch next batch​

thalabus current nodes and structure

Remember that the document node does not directly contain the embedding value.

Current model:

Document
├── Chapter(s)        ← embeddings here
│     └── Paragraph(s)  ← embeddings here
└── Summary           ← embedding here

Knowledge Base (Ontology) ACL

Knowledge Base resources (Ontologies and their children) are first-class ACL resources, integrated into the same permission system as Documents and Dossiers. No separate ACL service is introduced — all checks go through the existing IAclService. The unifying architectural marker is IAclResource, a common interface implemented by INeo4jOntology, INeo4jDocument, and INeo4jDossier.

KB Resource Hierarchy

🔖 Ontology          (top-level KB resource — direct ACL target)
  ├── 🧬 EntityOntology          ← [:CONTAINS] — inherits from Ontology
  ├── 🔗 RelationshipOntology    ← [:CONTAINS] — inherits from Ontology
  └── 🌐 Community               ← [:DEFINES]  — inherits from Ontology

Community nodes also carry the Dataset label (:Community:Dataset). Every Community is therefore usable through Dataset-oriented APIs, but the converse does not apply: a Dataset without the Community label is not an ontology-defined knowledge graph namespace.

Only the Ontology node holds direct GRANT relationships. Children inherit via ancestor-chain traversal extended to cover both [:CONTAINS] and [:DEFINES] relationships.

Applicable Permissions

Permission Ontology Children (inherited) Meaning for KB
READ X ✓ View schema and query the KB
ADD X Add entity/relationship type definitions
UPDATE X ✓ Edit schema definitions
DELETE X Delete the Ontology
SHARING X Manage ontology permissions
OWNERSHIP X Transfer ontology ownership

Roles

Same role table as Documents/Dossiers (Owner, Admin, Manager, Viewer). No new roles are introduced.

Ownership

Each Ontology is owned by a single group via (Group)-[:OWNS]->(Ontology). When a user creates an Ontology, their hidden personal group is granted Owner permissions atomically via AclService.SystemGrantPermissions(). The tenant admin group retains full bypass access via the existing SUPER_ADMIN mechanism.

Node Schema Additions

Node New Property Default Notes
Ontology isProtected false Reserved for future use. Since Ontologies have no parent, this currently has no effect on inheritance.

isDeleted / soft-delete are not added in this phase — Ontology deletion remains hard-delete.

Relationship Schema Additions

Relationship From To Description
[:GRANT:<PERMISSION>] Group Ontology Direct permission grant — same pattern as Document/Dossier
[:OWNS] Group Ontology Owner relationship — mandatory for all non-system Ontologies

ACL Evaluation

Evaluation order follows the standard Document/Dossier chain:

  1. Tenant-admin bypass (IsTenantAdmin check) — full access
  2. Direct [:GRANT:<PERMISSION>] on the Ontology node
  3. Inherited grants via ancestor chain (applies to EntityOntology, RelationshipOntology, Community)

The GetAncestorChain query in Neo4jAclRepository is extended from <-[:CONTAINS*]- to <-[:CONTAINS|DEFINES*]- so Community nodes correctly inherit from their parent Ontology. The same extension applies to AclQueryBuilder.AclFragment() for query-level filtering.

ACL Enforcement Points

Operation Required Permission
List / read ontologies READ
Add entity/relationship type ADD
Modify entity/relationship type UPDATE
Delete ontology DELETE
Manage permissions SHARING
Transfer ownership OWNERSHIP

Integration with Existing ACL System

KB resources reuse all existing ACL infrastructure without modification: - IAclService.CheckAccess() / GetAcl() / SetAcl() — label-agnostic, work on any node {id} - INeo4jAclRepository.MergePermissions() / DeletePermissions() — no changes needed - ResourceAclModal — wired to Ontology nodes in Ontology.razor via ResourceId = ontology.Id

The two infrastructure changes required are: 1. Extend the GetAncestorChain Cypher query in Neo4jAclRepository to traverse [:DEFINES]. 2. Extend AclQueryBuilder.AclFragment() to traverse [:DEFINES] for ACL-filtered list queries.

Bootstrap / Migration

On startup, BootstrapService calls INeo4jOntologies.BootstrapOntologyAcl(), which grants Owner permissions to the tenant admin group on all Ontology nodes that have no GRANT relationships. This is idempotent and runs on every startup (no-op after first run).