Feature: Lightweight Access Controls & Sharing Permissions
Problem
The current extension has no concept of identity beyond the local VS Code user. If Eric wants to share a curated project list or a workspace group with a teammate — or even just between his own personal and work VS Code profiles — there's no mechanism to do so without manually exporting/importing JSON. The fork goal mentions "teams or devices," which implies a need for scoped sharing.
Proposed Solution
Implement Share Links and Access Control Lists (ACLs) built on top of the Gist/HTTP sync backend. Keep it lightweight: no user database, no OAuth flows beyond the existing GitHub PAT.
Data Model
type ShareToken = string; // UUID v4, used in Gist filenames for isolation
type ShareConfig = {
token: ShareToken;
createdAt: number;
createdBy: MachineId;
name: string; // e.g., "Eric's Active Projects"
description?: string;
// ACL
mode: 'private' | 'link' | 'team';
allowedPats?: string[]; // SHA-256 hashes of GitHub PATs (for 'team' mode)
// In 'link' mode, anyone with the Gist URL can read; write requires the creator's PAT.
// Scope
includeProjects: string[]; // projectIds
includeTags?: string[];
includeGroups?: string[];
includeMetadata: boolean; // sync status/notes?
};
Sharing Flows
1. Create a Share
- Command:
Projects: Share Project Group
- User selects a workspace group or tag filter.
- Prompt: share mode (
private / link / team).
- If
team: prompt for GitHub usernames; extension looks up their public Gist profile (optional) or Eric distributes the token manually.
- Generates a
ShareConfig, writes it to the sync backend as share-<token>.json.
- Copies a share URL to clipboard:
https://gist.github.com/<user>/<gist-id>#share-<token>.
2. Join a Share
- Command:
Projects: Join Shared Project Group
- User pastes the share URL or token.
- Extension pulls
share-<token>.json, validates ACL, and merges included projects into local index.
- Shared projects appear in a new sidebar group: Shared →
<Share Name>.
3. Permissions Matrix
| Mode |
Read |
Write |
Admin |
private |
Creator only |
Creator only |
Creator |
link |
Anyone with URL |
Creator only |
Creator |
team |
Listed PATs |
Listed PATs |
Creator |
Write means: add/remove projects from the share scope, edit shared metadata.
Implementation Plan
Acceptance Criteria
Security Considerations
- Gists are either public or secret (unlisted). A
private share should use a private Gist or encrypt the ShareConfig with a passphrase before uploading.
- Never log or persist the GitHub PAT outside VS Code's
SecretStorage API.
- For
team mode, consider encrypting the project index with a shared symmetric key derived from the share token, so even if the Gist URL leaks, the data is unreadable without the token.
Feature: Lightweight Access Controls & Sharing Permissions
Problem
The current extension has no concept of identity beyond the local VS Code user. If Eric wants to share a curated project list or a workspace group with a teammate — or even just between his own personal and work VS Code profiles — there's no mechanism to do so without manually exporting/importing JSON. The fork goal mentions "teams or devices," which implies a need for scoped sharing.
Proposed Solution
Implement Share Links and Access Control Lists (ACLs) built on top of the Gist/HTTP sync backend. Keep it lightweight: no user database, no OAuth flows beyond the existing GitHub PAT.
Data Model
Sharing Flows
1. Create a Share
Projects: Share Project Groupprivate/link/team).team: prompt for GitHub usernames; extension looks up their public Gist profile (optional) or Eric distributes the token manually.ShareConfig, writes it to the sync backend asshare-<token>.json.https://gist.github.com/<user>/<gist-id>#share-<token>.2. Join a Share
Projects: Join Shared Project Groupshare-<token>.json, validates ACL, and merges included projects into local index.<Share Name>.3. Permissions Matrix
privatelinkteamWrite means: add/remove projects from the share scope, edit shared metadata.
Implementation Plan
src/sharing/ShareManager.ts.ShareConfigobjects stored as separate files in the same Gist (or sub-paths on HTTP backend).canRead(shareConfig, callerPatHash): booleancanWrite(shareConfig, callerPatHash): booleanShare This Group.Add to Share.Projects: Revoke Share— deletesshare-<token>.jsonfrom the backend.Acceptance Criteria
Security Considerations
privateshare should use a private Gist or encrypt theShareConfigwith a passphrase before uploading.SecretStorageAPI.teammode, consider encrypting the project index with a shared symmetric key derived from the share token, so even if the Gist URL leaks, the data is unreadable without the token.