Synopsis · Overview · Foundation · Implications · Containerization · Comparison · Rationale · Exploring · Future · Playground
SYNOPSIS
filesystem - Cylian Laboratory Console unified node-based filesystem. A novel approach to filesystem design where the traditional distinction between files and directories is abolished in favor of a unified node abstraction.
OVERVIEW
The Cylian Laboratory Console implements an experimental filesystem model that challenges conventional assumptions about hierarchical data organization. In traditional filesystems, entities are strictly categorized as either files (containing data) or directories (containing references to other entities). This dichotomy, while intuitive, imposes artificial constraints on how information can be structured and accessed.
This filesystem proposes a unified model where every entity is a node. Each node possesses both content (readable data) and children (traversable references), with access controlled independently through a permission system.
THEORETICAL FOUNDATION
The Node Abstraction
A node is defined as a tuple: N = (content, children, permissions) where:
content- The readable data contained in the nodechildren- A map of named references to other nodespermissions- Access control flags determining allowed operations
This model draws inspiration from several sources: the Unix “everything is a file” philosophy, hypertext systems where documents contain links, and object-oriented design where entities encapsulate both data and relationships.
Permission Model
Each node has five permission flags: r-t-w-u-x
r(read) - Content can be fetched and displayedt(traverse) - Children can be listed and accessedw(write) - Content can be modifiedu(update) - Children can be added or removedx(execute) - Node can be invoked as a command
Unlike traditional Unix permissions which conflate “list directory” with “read directory”, this model explicitly separates content access (r) from child traversal (t).
Group-Centric Permission Model
A fundamental departure from Unix: this filesystem abolishes the concept of owner. In traditional Unix, each file has exactly one owner (user) and one group, with three permission sets (owner/group/other). This creates asymmetry and complexity: the owner has special privileges, permission inheritance is awkward, and sharing requires careful group management.
In this model, permissions are defined per group only. Each node maintains a permission map:
"access": {
"admin": "rtwux",
"editor": "rtw--",
"guest": "r----"
}
This approach offers several advantages:
- No privileged owner - All access is mediated through group membership
- Multi-group permissions - The same node can have different permissions for different groups simultaneously
- Additive model - A user’s effective permissions are the union of all their group permissions
- Simpler ACLs - No need for separate ACL mechanisms; the access map IS the ACL
Rethinking setuid/setgid
With no owner, the traditional setuid concept becomes meaningless. There is no “owner identity” to assume during execution. Instead, privilege escalation is handled through setgid exclusively:
- setuid (obsolete) - No owner means no user identity to inherit. This permission flag is deprecated in this model.
- setgid (retained) - Execution can assume a specific group’s identity, granting the process that group’s permissions for the duration of execution.
The setgid mechanism is defined per-node with a target group:
"setgid": "admin"
When a node with setgid is executed, the process temporarily gains membership in the specified group, inheriting its permissions across the filesystem. This enables controlled privilege escalation without the security concerns of traditional setuid (which grants full user privileges).
Example: Privileged Command
/bin/shutdown
├── access: { "admin": "r---x", "guest": "----x" }
├── setgid: "admin"
└── content: shutdown script
A guest can execute shutdown (has x), but during execution, the process runs with admin group privileges due to setgid. The guest cannot read the script (no r), but admin can. This pattern replaces Unix setuid binaries with a more granular, auditable mechanism.
Implications for Security
- No root user - Privilege is distributed across groups, eliminating single points of compromise
- Principle of least privilege - setgid grants only the target group’s permissions, not full system access
- Auditability - Group membership is explicit and enumerable
- Revocability - Removing a user from a group immediately revokes all associated permissions
PRACTICAL IMPLICATIONS
Example 1: Self-Documenting Executables
Consider a command like /bin/ls. In a traditional filesystem, a binary contains compiled machine code, unreadable to humans. Documentation requires a separate file (man page) stored elsewhere. In this model:
/bin/ls
├── content: binary - compiled code
├── children: config/, man/
└── permissions: rt--x (readable + traversable + executable)
The command is executable, but also traversable: its children could include configuration files (ls /bin/ls/config) or embedded documentation (cat /bin/ls/man/usage). The binary itself remains readable for introspection tools. The same node serves as executable, configuration container, and documentation root.
Example 2: Documented Directories
In traditional filesystems, a directory cannot “contain” explanatory text - it can only contain files. Here, a node like /home/algorithm has both:
/home/algorithm
├── content: HTML page explaining the algorithm section
├── children: framogen, patricia-trie, ...
└── permissions: rt--- (readable + traversable)
Running cat /home/algorithm displays the explanatory content of this “directory”. Running ls /home/algorithm lists its children. Running cd /home/algorithm enters it. The node is simultaneously a document and a container.
Example 3: Configuration as Content
Imagine an executable that contains its own configuration:
/bin/server
├── content: { "port": 8080, "debug": true }
├── children: logs/, plugins/
└── permissions: rt--x (readable + traversable + executable)
The command can be executed, its configuration can be read (cat /bin/server), and its runtime artifacts can be explored (ls /bin/server). This eliminates the need for separate config file paths and creates a self-contained, introspectable service definition.
Example 4: Encapsulated Dependencies
A binary may contain internal plugins or libraries that should remain hidden from users:
/bin/compiler
├── content: binary - compiled code
├── children: plugins/, libs/, cache/
└── permissions: ----x (executable only)
The command can be executed, but its internal structure is opaque. Running ls /bin/compiler fails (no t permission). Running cat /bin/compiler fails (no r permission). The plugins and libraries exist as children but are only accessible to the binary itself during execution. This pattern enables:
- Encapsulation - Implementation details hidden from users
- Security - Internal components cannot be inspected or tampered with
- Simplicity - Users see only the command, not its dependencies
Contrast with traditional Unix where shared libraries in /lib are globally visible and accessible.
Example 5: Clean Uninstallation
Removing an application - a word processor, a web browser, or any complex software - is simply deleting its node:
rm /bin/browser
Since all dependencies, plugins, configuration, and cache live as children of the application node, everything is removed in one operation. No orphaned config files scattered in ~/.config, no forgotten plugins in /usr/share, no complex uninstall scripts. The node IS the application boundary.
Traditional systems suffer from:
- Config scatter - Settings in
~/.config,/etc, registry, environment variables - Orphaned files - Uninstallers miss files, leaving debris
- Shared dependencies - Cannot remove libraries that might be used elsewhere
- Complex scripts - Uninstall procedures that may fail or be incomplete
In this model, application boundaries are explicit and total. Delete the node, delete everything.
NATIVE CONTAINERIZATION
Traditional containerization (Docker, LXC, etc.) emerged to solve a fundamental problem: applications depend on libraries, configurations, and runtime environments scattered across the filesystem. Containers bundle everything into an isolated image, but this introduces complexity: layered filesystems (UnionFS), image registries, and specialized tooling.
In this filesystem model, the container format is native. While orchestration tools (Docker, Kubernetes, YAML manifests) remain necessary for deployment, scaling, and lifecycle management, the output of containerization is simply a node:
/bin/webapp
├── content: binary - application server
├── children:
│ ├── libs/ # Dependencies
│ ├── config/ # Configuration files
│ ├── static/ # Static assets
│ ├── data/ # Runtime data
│ └── logs/ # Log output
└── permissions: rt--x
The Node IS the Container
Docker’s UnionFS and image layering remain essential for building and managing images efficiently. However, the final artifact - the container itself - maps directly to a node. The node encapsulates:
- Code - The executable content
- Dependencies - Libraries as children nodes
- Configuration - Config files as children or inline content
- State - Runtime data in child nodes
- Isolation - Permission boundaries control access
Image Building vs Runtime
The distinction is important:
- Build time - Docker, Dockerfiles, multi-stage builds, layer caching - all still necessary for efficient image creation
- Runtime - The resulting container is a node, inspectable with standard filesystem commands
- Orchestration - Kubernetes, Docker Compose, YAML manifests - still required for deployment, scaling, networking
Deployment Benefits
Once built, nodes are self-contained and portable. Each node carries its own dependency versions:
/bin/webapp-v1/libs/crypto # version 1.2
/bin/webapp-v2/libs/crypto # version 2.0
Both versions coexist without conflict. No global package manager, no version resolution at runtime.
Comparison with Traditional Containers
| Aspect | Docker/OCI | Node-based |
|---|---|---|
| Build tools | Dockerfile, BuildKit | Same (produces nodes) |
| Image format | Layered image files | Filesystem nodes |
| Registry | Separate infrastructure | The filesystem itself |
| Orchestration | Kubernetes, Compose | Same (operates on nodes) |
| Inspection | docker inspect | Standard commands (ls, cat) |
| Isolation | Kernel namespaces | Permission boundaries |
What Changes, What Remains
- Changed - Container format (nodes instead of layered images)
- Changed - Inspection (standard filesystem tools instead of specialized commands)
- Unchanged - Build process (Dockerfiles, multi-stage builds, layer caching)
- Unchanged - Orchestration (Kubernetes, manifests, service mesh)
- Unchanged - Networking, volumes, secrets management
COMPARISON WITH TRADITIONAL MODELS
Unix Filesystem
| Feature | Unix | Cylian Laboratory Console |
|---|---|---|
| Entity types | Files, directories, links, devices, … | Nodes only |
| Directory content | None (implicit list) | Explicit addressable resource |
| File children | Impossible | Allowed (with t permission) |
| Permission model | rwx per user/group/other | rtwux per user |
Hypertext / Web
Web pages naturally combine content with links (children). However, the web lacks a hierarchical namespace and consistent permission model. This filesystem brings web-like flexibility to a structured hierarchy.
Object Databases
Object databases store entities with both properties (content) and relationships (children). This filesystem can be viewed as a navigable object graph with URL-based content resolution.
DESIGN RATIONALE
Why Unify Files and Directories?
The file/directory distinction is a historical artifact. Early filesystems needed to differentiate storage strategies: files were contiguous byte streams, directories were specialized index structures. Modern filesystems already blur this line (Unix directories are “special files”), but the API maintains the fiction.
By removing this distinction, we gain:
- Simplicity - One abstraction instead of two
- Flexibility - Any node can gain children over time
- Discoverability - Containers can explain themselves
- Uniformity - Same operations work on all nodes
Why Separate Read and Traverse?
In Unix, r on a directory means “list contents” - but what if you want to allow listing without allowing content access, or vice versa? Separating r (content) from t (children) enables fine-grained control:
r----- Readable but not traversable (opaque document)-t---- Traversable but not readable (index without landing page)rt---- Both (typical parent node)
EXPLORING THE FILESYSTEM
Use these commands to explore the node structure:
ls -l # List with permissions and types
stat <path> # Full node metadata
file <path> # Content type only
cat <path> # Fetch and display content
open <path> # Open content in browser
Try examining different node types:
stat /bin/ls # Executable with readable source
stat /home # Node with content and children
ls -f /home # Tree view of all nodes
FUTURE DIRECTIONS
This filesystem model opens possibilities for:
- Version control - Nodes could have temporal children (revisions)
- Symbolic computation - Content could be dynamically generated
- Federated namespaces - Children could reference remote nodes
- Schema validation - Content types could enforce structure
PLAYGROUND
Try the filesystem in the Laboratory Console
AUTHOR
Cylian Laboratory Console Filesystem - Cylian Research