78 lines
3.9 KiB
Markdown
78 lines
3.9 KiB
Markdown
# Decision 0002: Shared, Readable Pipeline Filesystem Policy
|
|
|
|
Status: accepted
|
|
|
|
Date: 2026-09-14
|
|
|
|
## Context
|
|
|
|
The D&D pipeline may be invoked either by its dedicated `narratio` service
|
|
account or by a human operator who is already a member of the `narratio`
|
|
group. Both identities need a consistent view of application configuration and
|
|
shared writable state. Notarius versions before v0.7.0 imposed private cache
|
|
modes that prevented this deployment model, but v0.7.0 delegates cache access
|
|
policy to deployment provisioning.
|
|
|
|
The pipeline processes D&D campaign material. This deployment does not treat
|
|
configuration, transcripts, caches, generated artifacts, logs, or other
|
|
pipeline content as secret. API keys and similar credentials are the sole
|
|
confidential category and must remain isolated from ordinary content.
|
|
|
|
## Decision
|
|
|
|
The suite uses `narratio` as both its service identity and shared operator
|
|
group. A human account that is already a member of that group is a supported
|
|
pipeline invocation identity. Selecting operators and managing their group
|
|
membership remain separate deployment concerns.
|
|
|
|
Application configuration directories and files are owned by
|
|
`narratio:narratio` and are world-readable. Directories normally use `0755`
|
|
and files use `0644`. They remain Ansible-managed even though the service
|
|
account owns them; operators do not edit managed configuration in place.
|
|
Standalone application roles expose generic owner, group, and mode variables
|
|
and retain independently useful defaults. The opinionated pipeline role
|
|
selects the suite ownership policy through those interfaces.
|
|
|
|
Shared writable roots use `narratio:narratio` ownership and mode `2775`.
|
|
Setgid preserves the shared group, while managed default ACLs preserve owner
|
|
and group write access and world read/traverse access for newly created
|
|
content regardless of an invoking account's ordinary umask. Ordinary files
|
|
are expected to converge to the corresponding non-executable mode `0664`.
|
|
Application source trees and installed binaries remain root-owned and
|
|
world-readable or executable as appropriate.
|
|
|
|
Credential material belongs only beneath the suite's eventual `secrets/`
|
|
directory. That directory is not world-accessible; its expected directory and
|
|
file modes are `0750` and `0640`, respectively, with
|
|
`narratio:narratio` ownership so both supported invocation identities can read
|
|
shared credentials. Configuration may contain credential reference names but
|
|
never raw credential values.
|
|
|
|
Narratio's general operational guidance recommends `0700` directories and
|
|
`0600` files for a single-user credential store. The suite deliberately grants
|
|
group read/traverse access instead: membership in the selected `narratio`
|
|
runtime group authorizes both pipeline execution and use of its shared provider
|
|
credentials. Deployments that do not trust every group member require a
|
|
different per-user credential policy and are outside this decision.
|
|
|
|
Version-controlled campaign and prompt assets may remain root-managed because
|
|
Git is authoritative, but they are world-readable. The suite does not add
|
|
confidentiality controls to non-secret D&D content.
|
|
|
|
## Consequences
|
|
|
|
The pipeline can run under the service account or an existing human member of
|
|
the shared group without maintaining separate configuration or cache trees.
|
|
The deployment must provision setgid and default ACL behavior on shared
|
|
writable roots; directory modes alone do not guarantee group write access for
|
|
content created under an arbitrary user umask.
|
|
|
|
The broad readability of transcript-derived content is intentional. Hosts
|
|
requiring confidential campaign data need a different deployment policy and
|
|
are outside this MVP contract. Secret delivery remains future work and must
|
|
honor the separate restricted subtree rather than tightening unrelated files.
|
|
|
|
Existing content with incompatible ownership or ACLs is not recursively
|
|
migrated unless a feature expressly selects that behavior. Fresh convergence
|
|
and newly created content follow this policy.
|