.cairn-state/ must be invisible and unreachable from every user surface #155
Labels
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Cordy/Cairn#155
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Depends on #152 (prefix decided). The reserved prefix holds ciphertext credentials; no user-facing surface may list, read, write, share, or deliver into it — including admins, whose unscoped view addresses the whole backend.
Surfaces to gate, each with a test:
.cairn-statefiltered from root listings and rejected as a path component..cairn-statepath refused; existing-share resolution cannot traverse into it./home/…, add the explicit test anyway..cairn-state(or the prefix appearing under/spaces) cannot be created.Implementation choice to make: one guard at the storage-driver boundary (a
reserveddecorator innermost, mirroring how scope works outermost) versus per-surface checks. The decorator is one place to be right; record the choice. Note the guard must NOT block the statestore itself — it goes through the raw driver below the decorator.Also: root listings for unscoped admins hide the prefix (like dotfiles are handled today, but enforced server-side, not cosmetically).
Shipped in v0.5.5 (PR #165), live on the dogfood.
Implementation choice, recorded: one guard at the storage-driver boundary —
internal/storage/reserved, an INNERMOST decorator mirroring scope's outermost position — rather than per-surface checks. Every surface this issue lists (REST file API, WebDAV, trash/restore, share resolution, spaces, peering delivery) addresses storage through the decorated stack, so one guard covers them all, unscoped admins included, enforced server-side. The statestore holds the raw driver captured before the wrap, so state operations pass underneath by construction (proven by testTestRawDriverBelowGuardStillReachesState).Scope decisions:
/.cairn-stateAND/.cairnare blocked as root subtrees — the posix state directory holds the same secret class (auth verifiers, peering credentials) and was previously admin-downloadable. The.cairn-statename is additionally blocked as a segment anywhere, so a space or folder named after the prefix cannot be created on any surface (covers the spaces requirement without touching spaces code). A deep directory legitimately named.cairnremains ordinary content. Blocked paths answerErrNotFound, never "forbidden": confirming existence would leak what the guard hides. Like scope, the decorator does NOT embedstorage.Driver— every method explicit, so an interface addition can never silently bypass it.Usageforwarded for quota.Tests: root listing hides both entries; all eight ops (List/Stat/Open/Write/Delete/Mkdir/Rename/Copy, both directions for the two-path ops) return ErrNotFound on six representative reserved paths; the sentinel still satisfies
fs.ErrNotExist(the #153 lesson, now regression-tested); nested.cairnallowed; ordinary content untouched.