Skip to content

Feature: Lightweight Access Controls & Sharing Permissions #55

Description

@EricGrill

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

  • Phase 1: Share Manager
    • Create src/sharing/ShareManager.ts.
    • CRUD operations for ShareConfig objects stored as separate files in the same Gist (or sub-paths on HTTP backend).
  • Phase 2: ACL Engine
    • canRead(shareConfig, callerPatHash): boolean
    • canWrite(shareConfig, callerPatHash): boolean
    • Hash the local PAT with SHA-256 at runtime; never store the raw PAT in the index.
  • Phase 3: UI for Sharing
    • Context menu on workspace group: Share This Group.
    • Context menu on project: Add to Share.
    • New sidebar section under Tags: Shared Groups.
    • Inline badge on shared projects showing the share name.
  • Phase 4: Revocation & Expiry
    • Projects: Revoke Share — deletes share-<token>.json from the backend.
    • Optional expiry date on share links (auto-cleanup via a cron-like check on startup).

Acceptance Criteria

  • Eric can create a share link for his "CafeJusto" workspace group and send it to a teammate.
  • The teammate can join the share and see the same project list + tags in their VS Code sidebar.
  • If Eric updates a shared project's tag, the teammate sees the change on next sync.
  • Revoking a share immediately removes it from the teammate's sidebar on next sync (or within 5 minutes).

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions