Skip to content

feat(storage)!: storage authz completion - #1279

Open
ChrisPdgn wants to merge 5 commits into
mainfrom
v-next-storage-authz
Open

ChrisPdgn wants to merge 5 commits into
mainfrom
v-next-storage-authz

Conversation

@ChrisPdgn

@ChrisPdgn ChrisPdgn commented Jan 21, 2025

Copy link
Copy Markdown
Contributor

This PR implements #1173. Please check in there for more details.

Breaking change:

  • Client routes no longer allow container creation

Additional features:

  • If no folder is provided in file creation, a personal folder is created with name cnd_${user._id}

Bugs found & fixes:

  • Admin endpoint for folder deletion did not delete subfolders and subfolder files
  • Container deletion in local provider was not possible

Notes:

  • Containers can own files directly if file folder is '/', otherwise they can own folders that can own folders or files, e.tc.
  • Admin users can create scoped containers, but default container cannot be owned
  • Admin users can create scoped folders with admin endpoint & client users can create scoped folders through file creation (if allowed to do so)

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update
  • Refactor
  • Build-related changes
  • Other (please describe)

Does this PR introduce a breaking change?

  • Yes
  • No

The PR fulfills these requirements:

  • It's submitted to the main branch
  • When resolving a specific issue, it's referenced in the PR's description (e.g. fix #xxx, where "xxx" is the issue number)

If adding a new feature, the PR's description includes:

  • A convincing reason for adding this feature

Other information:

@ChrisPdgn ChrisPdgn changed the title feat(storage): storage authz completion feat(storage)!: storage authz completion Jan 22, 2025
@kkopanidis
kkopanidis requested a review from kon14 January 22, 2025 12:01
@ChrisPdgn
ChrisPdgn marked this pull request as draft September 8, 2026 14:26
Register Container, Folder, and File as a filesystem-shaped ReBAC
tree using the current oncePeerUp authz lifecycle.

Client file APIs no longer create missing containers. An omitted
folder resolves to a personal cnd_<userId>/ folder, and creating
under another user's missing personal root is denied.

Fixes #1173

BREAKING CHANGE: Client storage APIs return 404 for missing
containers instead of creating them. An omitted folder now
creates cnd_<userId>/.
Share admin container/folder setup, resolve file ids consistently,
and drop the unused getFileUrl fallback.
Keep implementation files in authz/ and handlers/ and collect the
authz coverage in one dedicated test folder.
@cursor
cursor Bot force-pushed the v-next-storage-authz branch from b7a5505 to 6104ff6 Compare September 9, 2026 09:04
@cursor
cursor Bot changed the base branch from v-next to main September 9, 2026 09:04
Skip can(edit) on leftover unowned folders and named containers,
heal them on first write, and always stamp scope ?? User on File
creates. Deny unmanaged cnd_<other>/ squats. No second flag and
no reconstruct job. Old files are not backfilled.

Sibling-file A1 scans were explicitly rejected.
Admin without scope still owns a folder via the container only.
On the default container that locks Client users out; pass a scope
when the folder should stay Client-writable.
@cursor

cursor Bot commented Sep 15, 2026

Copy link
Copy Markdown

What landed after the earlier rewrite (6104ff6944300007)

The first three commits on this branch (831c423c, e4daed6d, 6104ff69) already shipped the greenfield filesystem ReBAC tree. These two follow-ups make that tree upgrade-safe. No second flag. No reconstruct job. No fyllo code. Sibling-file A1 scans were considered and rejected.

Commits

  • 20d2d62efix(storage): make filesystem ReBAC upgrade-safe
  • 44300007docs(storage): note Admin scope is optional but needed for Client writes

Files: authz/relations.ts, authz/folders.ts, handlers/file.ts, admin/adminFile.ts, authz unit tests, modules/storage/README.md, CHANGELOG.md.

Behavior added

A1 — Unowned = unmanaged

  • A leftover folder/named container with no owner/editor/reader relations (findRelation, fail closed) does not can(edit).
  • Walk through unmanaged ancestors; can(edit) only on the nearest managed folder.
  • Unmanaged named container: skip container can(edit). Default container: never checked, never owned.

Squat harden

  • Client: cnd_<other>/ is denied if that personal root is missing or unmanaged.
  • If it is already managed: normal folder checks (Alice may have granted Bob).
  • Admin: still no squat.

A2 — Always stamp the creating actor on File

  • After the structural Folder/Container owner, Client creates always also write scope ?? User:<id> on the File (not only when folder === '/').
  • Admin / gRPC with no userId: do not invent a user.

A3 — Heal on first write

  • Existing unowned folders get structural + current subject (like a new first folder / nested + subject).
  • Unowned named containers get the current subject when one is present, including writes at /.
  • Default container is never healed/owned.
  • Old files are not backfilled.

A4 — Moves / deletes

  • On path change with authz on: always try to remove the old structural owner (ignore missing row/relation); add the new one.
  • Folder/container delete still pages File + Folder + Container relation cleanup (ignore missing).

A5 kept as-is

  • Client missing container → 404; omitted folder → cnd_<userId>/; public getFile/getFileUrl; gRPC params.id; 403/404 not wrapped as 500; Admin can create containers, Client cannot; oncePeerUp authz lifecycle.

Docs (A6 + Admin scope)

README + CHANGELOG now also say:

  • Client breaks: container 404, personal folder, squat, scope create read → edit.
  • No reconstruct; heal on first write; no second flag.
  • Provision named containers via Admin. Fyllo-like apps keep authorization.enabled: false until per-user roots + per-file grants or privileged fetch.
  • Admin scope is optional (not an error). If Admin writes into a leftover/new folder without scope, the folder becomes container-owned. On the default container, later Client writes get 403. To keep it Client-writable: pass a scope, or let a Client user write first.

Tests

Storage unit suite: 95 passed (upgrade leftover, squat unmanaged, walk-to-managed-parent, A2 nested actor, heal including /, move ignore-missing, cascade ignore-missing, no file backfill).

Residual risks (accepted, documented)

  1. Two different users (no shared Team scope) hitting a fully unmanaged folder at the same instant can both become owners. Same Team: scope is fine — one tuple.
  2. Old private files with no File relation stay Client-dark after enable; Admin can still serve them.
  3. Admin without scope claiming a leftover folder → container-owned → Client 403 on default container (documented; not enforced).
  4. Moving an old File with no actor to / on the default container leaves only Container#owner@File.

Still draft. No new PR. Sibling-file A1 was explicitly not implemented.

@ChrisPdgn
ChrisPdgn marked this pull request as ready for review September 15, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants