Data Architecture & Filesystem Governance¶
Status: Normative (Mandatory) · Implemented: Partial (since v0.1.0) — Two-Worlds separation and init script are AS-IS; full access control matrix is TO-BE Scope: System-wide (Host & Container) OS Target: Fedora Linux (SELinux Enforcing) with Rootless Podman
This document defines the strict governance rules for file storage, container access control, and directory structures within the Silvasonic ecosystem.
1. The "Two-Worlds" Architecture Principle¶
See ADR-0005 for the architectural decision behind this principle.
The system makes a strict distinction between immutable code (Repository) and mutable state (Workspace). These two worlds must never mix.
World A: The Repository (Immutable Code)¶
- Path:
SILVASONIC_REPO_PATH(Default:/mnt/data/dev/apps/silvasonic) - Content: Source code, scripts, configuration templates, Ansible playbooks.
- Access Rule:
- Containers have Read-Only access.
- Exception: In "Development Mode" (Live-Reload), containers may temporarily have write access to source files.
- Strict Prohibition: Production data (WAVs, DB files) must NEVER be stored here.
World B: The Workspace (Mutable State)¶
- Path:
SILVASONIC_WORKSPACE_PATH(Default:/mnt/data/dev_workspaces/silvasonic) - Content: Audio recordings, configuration files, service-specific data.
- Access Rule:
- This is the only location where containers are permitted to persist data.
- Deleting this directory is equivalent to a "Factory Reset".
2. Domain-Driven Workspace Structure¶
The Workspace directory must be strictly organized by service. There is no "common dumping ground". Each service owns a dedicated directory.
Directory Standards¶
The root of the Workspace must contain only folders matching the service names defined in compose.yml. The init.py script creates only these top-level service directories. All internal structure within a service directory is created dynamically at runtime by the respective service or the Controller.
-
controller/:- Orchestration state and configuration.
- Internal structure is created by the Controller at startup.
-
recorder/:- Internal structure is created dynamically by the Controller when a new microphone is registered.
- Creates a subdirectory per microphone:
recorder/{MIC_NAME}/ - Must contain
.buffer/rawinside the mic folder. - Must contain
.buffer/processedinside the mic folder. - Must contain
data/rawinside the mic folder. - Must contain
data/processedinside the mic folder.
NOTE:
databaseuses a Named Volume and does not reside in the user-accessible Workspace to prevent permission errors and accidental corruption.
Logging Policy¶
- Services must output structured JSON logs to
stdout. - The container runtime (Podman) is responsible for capturing, rotating, and persisting logs.
- There are no file-based log directories in the Workspace.
3. Access Control & Zero Trust (Shared Access)¶
Containers are not granted blanket access to the entire Workspace. The Controller, as the system orchestrator, has elevated privileges, while other services operate under strict scoping.
The Controller Authority (System Orchestrator)¶
- The Controller service is the "Boss" of the system.
- It is explicitly granted Read-Write access to all service workspace directories (e.g.,
recorder/) to manage configuration, create directory structures (e.g.,{MIC_NAME}folders), and orchestrate lifecycles.
Service Scoping (The Worker Principle)¶
- Worker services (like
recorder) are scoped to their specific domain. - They have Read-Write access only to their own root folder.
- Example: The
recordercontainer writes its data into/recorder/{MIC_NAME}/, but the directory structure is provisioned by the Controller.
The Consumer Principle (Read)¶
- If a service needs data from another, that folder must be mounted Read-Only.
- Strict Rule: A downstream service must never delete or modify original raw data.
4. OS-Compliance & Podman Configuration¶
As the host is Fedora with SELinux, all container definitions must adhere to the following technical requirements:
Mount Strategy¶
- Host Bind Mounts are mandatory for all User Data (Recordings, Configs).
- Each service mounts its entire Workspace subdirectory as a single volume (e.g.,
workspace/recorder:/app/workspace:z). - Named Volumes: Are permitted only for
databaseinternal state.
SELinux Labeling¶
- All Bind Mounts in the Workspace must be suffixed with
:z(lowercase). - This marks content as "Shared Content", readable by multiple containers (Writer and Reader) and the host.
- Prohibited: The use of
:Z(Private Content) is forbidden for shared data folders (likedata) as it blocks access for other containers.
5. Lifecycle & Initialization¶
The filesystem state must not be left to chance ("container runtime creating folders as root").
Init Process¶
- An initialization script (
scripts/init.py) must run before containers start. - This script creates the service root directories only (
controller/,recorder/). - Internal directory structures within each service are created dynamically by the Controller or the respective service at runtime.
- It must ensure all folders are owned by the host user and have
755(rwxr-xr-x) permissions.
Clean-Up / Reset¶
- A "Factory Reset" is defined as the deletion of all content within the Workspace path.
- The folder structure should be immediately reconstructible by re-running the Init Script.