-
Notifications
You must be signed in to change notification settings - Fork 0
feat(server): add project scope and collaboration foundations #230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
cb015fd
feat(server): add project collaboration foundations
YaoYinYing f9c9254
feat(server): make project scope authoritative
YaoYinYing ed0e921
fix(server): harden project scope identity and lifecycle
YaoYinYing 060c701
fix(server): close project result visibility contract
YaoYinYing a3aaf7f
fix(server): make project archival mutations atomic
YaoYinYing 94c7da3
fix(ui): require explicit scope fallback
YaoYinYing File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| # Project Scope, Storage, and Artifact References | ||
|
|
||
| REvoCompute tasks belong to exactly one authoritative scope. Scope controls | ||
| authorization, discovery, storage, and artifact reuse; it is not presentation | ||
| metadata. | ||
|
|
||
| ```text | ||
| User | ||
| | | ||
| +-- Personal Scope | ||
| | `-- Task | ||
| | `-- Artifact | ||
| | | ||
| `-- Project Membership | ||
| `-- Project Scope | ||
| `-- Task | ||
| `-- manifest Artifact | ||
| `-- ArtifactReference | ||
| `-- downstream Task input snapshot | ||
| ``` | ||
|
|
||
| ## Authorization | ||
|
|
||
| Global account roles (`admin`, `user`, and `guest`) remain independent from | ||
| Project roles. Project roles are `owner`, `maintainer`, `contributor`, and | ||
| `viewer`; the collaboration service maps them to explicit capabilities. | ||
| Routes ask capability questions rather than interpreting role names. | ||
|
|
||
| Visibility controls non-member discovery and reading: | ||
|
|
||
| - `private`: members only; unknown callers receive the same response as a | ||
| missing Project. | ||
| - `internal`: authenticated non-members may discover the read-only Project | ||
| surface. | ||
| - `public`: anonymous callers may discover the read-only Project surface. | ||
|
|
||
| Visibility does not grant membership, submission, artifact reuse, diagnostic | ||
| downloads, or future runner-policy eligibility. A viewer can read Project | ||
| results but cannot reuse artifacts. Task mutation requires `cancel_own_tasks` | ||
| or `cancel_project_tasks`, independently of read access. | ||
|
|
||
| ## Scoped storage | ||
|
|
||
| Usernames and Project names are presentation metadata. Each user and Project | ||
| receives a persistent storage key with a readable initial prefix and random | ||
| opaque suffix. Renames never update that key or move result trees. | ||
|
|
||
| New task paths are resolved only by `StorageResolver`: | ||
|
|
||
| ```text | ||
| results/ | ||
| users/<user-storage-key>/tasks/<task-id>/ | ||
| projects/<project-storage-key>/tasks/<task-id>/ | ||
| ``` | ||
|
|
||
| Input snapshots use the same scope hierarchy beneath the configured input | ||
| root. The physical hierarchy is an implementation detail and not an API. | ||
| Routes, workers, Docker/SLURM jobs, manifest finalization, archives, recovery, | ||
| and cleanup resolve paths from the persisted task scope. | ||
|
|
||
| Project Scope ships with a fresh schema contract. Deployments adopting this | ||
| version rebuild the REvoCompute databases and storage roots; there is no old | ||
| task-layout resolver or username-based fallback. Every task row is complete at | ||
| creation and every path is derived from its immutable scope identity. | ||
|
|
||
| This release is a new persistent-state epoch. Startup validates the user, task, | ||
| and collaboration schemas before serving work. Reusing an older or partial | ||
| schema fails with an operator-facing reset message; startup never alters, | ||
| backfills, guesses, or deletes persistent state. | ||
|
|
||
| For the one-time development upgrade, stop REvoCompute, deliberately remove the | ||
| test-era user/task/collaboration databases and old workspace/results roots, | ||
| then start the release and recreate users and Projects. Ordinary restarts do | ||
| not perform this reset and must preserve the current databases and scoped | ||
| storage roots. | ||
|
|
||
| Tasks persist two independent immutable identities: `scope_type` plus | ||
| `scope_id` determines where the task belongs, while `submitted_by_user_id` | ||
| records who submitted it. The optional username value is a historical display | ||
| snapshot only and is never an authorization primitive. | ||
|
|
||
| ## Artifact references | ||
|
|
||
| An input may use `@<task-id>/<logical-artifact-path>`. This is submission syntax | ||
| only. Before any physical lookup, the server loads the source task and checks | ||
| that the caller may reuse artifacts in the same Personal or Project scope. | ||
| Cross-user and cross-Project reuse is denied. | ||
|
|
||
| When a Project is archived, eligible members may snapshot its finalized | ||
| manifest artifacts into their Personal scope. This narrow frozen-record rule | ||
| does not permit submission into the archived Project or Project-to-Project | ||
| sharing. | ||
|
|
||
| The storage resolver then requires a finalized source task and an exact entry | ||
| in its authoritative result manifest. It rejects absolute paths, traversal, | ||
| empty path segments, symlinks, missing files, and content that no longer | ||
| matches the manifest hash or size. The caller never supplies or receives a | ||
| host, container, SLURM, or storage-key path. | ||
|
|
||
| An authorized artifact is copied into the downstream task's immutable input | ||
| snapshot and appears to the runner as an ordinary local input. Provenance | ||
| records the downstream input, source task and scope, logical artifact path, | ||
| SHA-256, size, media type, and timestamp. | ||
|
|
||
| ```text | ||
| provenance propagates | ||
| permissions do not | ||
| ``` | ||
|
|
||
| Archiving or renaming the source scope therefore cannot mutate a submitted | ||
| downstream task, and access to the downstream task does not grant access to the | ||
| upstream task. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For an anonymous visitor to a public project, the new project API grants
view_resultsand returns the task list, but this helper always rejects the visitor and every result/status/artifact GET route remains protected bylogin_required. Consequently, the advertised public read-only flow stops at the task list; the public read routes need optional authentication and should evaluate project visibility with aNoneuser ID.Useful? React with 👍 / 👎.