Skip to content

Commit a12606d

Browse files
authored
Merge pull request #639 from rajbos/rajbos/plan-sharing-server-design
feat: self-hosted sharing server (Phases 1–3)
2 parents eaeda36 + d414a41 commit a12606d

42 files changed

Lines changed: 3794 additions & 292 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ visualstudio-extension/src/CopilotTokenTracker/obj/project.nuget.cache
2323
visualstudio-extension/src/CopilotTokenTracker.Tests/bin/
2424
visualstudio-extension/src/CopilotTokenTracker.Tests/obj/
2525
visualstudio-extension/TestResults/
26+
vscode-extension/.session_secret.txt

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,48 @@ npx @rajbos/ai-engineering-fluency stats
8888

8989
---
9090

91+
### 🔗 Self-Hosted Sharing Server
92+
93+
Share usage data with your team without an Azure account. Run a lightweight API server
94+
on your own infrastructure — team members configure a single endpoint URL and upload
95+
automatically via their existing GitHub session.
96+
97+
- **Zero Azure required** — SQLite + Docker, runs anywhere
98+
- **Auth via GitHub** — reuses the session already held by VS Code/Copilot, no API keys
99+
- **Optional org gating** — restrict uploads to GitHub org members
100+
- **Web dashboard** — see aggregated usage across your team
101+
102+
```yaml
103+
# docker-compose.yml
104+
services:
105+
sharing-server:
106+
image: ghcr.io/rajbos/copilot-sharing-server:latest
107+
ports:
108+
- "3000:3000"
109+
environment:
110+
- GITHUB_CLIENT_ID=...
111+
- GITHUB_CLIENT_SECRET=...
112+
- SESSION_SECRET=...
113+
- BASE_URL=https://copilot.example.com
114+
volumes:
115+
- sharing_data:/data
116+
volumes:
117+
sharing_data:
118+
```
119+
120+
```json
121+
// VS Code settings — the only thing team members configure
122+
{
123+
"copilotTokenTracker.backend.enabled": true,
124+
"copilotTokenTracker.backend.backend": "sharingServer",
125+
"copilotTokenTracker.backend.sharingServer.endpointUrl": "https://copilot.example.com"
126+
}
127+
```
128+
129+
📖 [Full sharing server documentation](sharing-server/README.md)
130+
131+
---
132+
91133
## Contributing
92134

93135
Interested in contributing? Check out our [Contributing Guide](CONTRIBUTING.md) for:

build.ps1

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@
88
Projects:
99
vscode-extension – VS Code extension (TypeScript / Node.js)
1010
cli – Command-line tool (TypeScript / Node.js)
11+
sharing – Self-hosted sharing server (TypeScript / Node.js)
1112
visualstudio-extension – Visual Studio extension (C# / .NET) [future]
1213
1314
.PARAMETER Project
14-
Which project(s) to build. Accepts: all | vscode | cli | visualstudio
15+
Which project(s) to build. Accepts: all | vscode | cli | sharing | visualstudio
1516
Default: all
1617
1718
.PARAMETER Target
@@ -28,7 +29,7 @@
2829
#>
2930

3031
param(
31-
[ValidateSet('all', 'vscode', 'cli', 'visualstudio')]
32+
[ValidateSet('all', 'vscode', 'cli', 'visualstudio', 'sharing')]
3233
[string] $Project = 'all',
3334

3435
[ValidateSet('build', 'package', 'test', 'clean')]
@@ -195,16 +196,34 @@ function Build-VisualStudio {
195196
}
196197

197198
# ---------------------------------------------------------------------------
198-
# Entry point
199+
# Sharing Server
199200
# ---------------------------------------------------------------------------
201+
function Build-Sharing {
202+
Write-Step "sharing-server: $Target"
203+
Push-Location "$PSScriptRoot/sharing-server"
204+
try {
205+
switch ($Target) {
206+
'build' { npm ci; npm run build }
207+
'package' { npm ci; npm run build:production }
208+
'test' { Write-Host " (no sharing-server tests yet)" }
209+
'clean' { Remove-Item -Recurse -Force dist -ErrorAction SilentlyContinue }
210+
}
211+
Write-Ok "sharing-server done."
212+
}
213+
finally { Pop-Location }
214+
}
215+
216+
200217
switch ($Project) {
201218
'all' {
202219
Build-VsCode
203220
Build-Cli
221+
Build-Sharing
204222
Build-VisualStudio
205223
}
206224
'vscode' { Build-VsCode }
207225
'cli' { Build-Cli }
226+
'sharing' { Build-Sharing }
208227
'visualstudio'{ Build-VisualStudio }
209228
}
210229

sharing-server/.env.example

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Copy this file to .env and fill in the values before running docker-compose
2+
3+
# GitHub OAuth App credentials (create at https://github.com/settings/developers)
4+
# Set Callback URL to: <BASE_URL>/auth/github/callback
5+
GITHUB_CLIENT_ID=your_github_client_id_here
6+
GITHUB_CLIENT_SECRET=your_github_client_secret_here
7+
8+
# Random secret for signing session cookies
9+
# Generate with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
10+
SESSION_SECRET=change_me_to_a_random_secret
11+
12+
# Public base URL of this server (used in OAuth redirect URI and links)
13+
BASE_URL=http://localhost:3000
14+
15+
# Optional: restrict to members of a specific GitHub organization
16+
# Leave empty to allow any GitHub user
17+
ALLOWED_GITHUB_ORG=

sharing-server/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules/
2+
dist/
3+
data/
4+
*.db
5+
.env

sharing-server/Dockerfile

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# syntax=docker/dockerfile:1
2+
3+
# ── Build stage ──────────────────────────────────────────────────────────────
4+
# Uses node:sqlite (built-in, no native compilation needed)
5+
FROM node:24-slim AS builder
6+
7+
WORKDIR /app
8+
9+
COPY package*.json ./
10+
RUN npm ci
11+
12+
COPY . .
13+
RUN npm run build:production
14+
15+
# ── Runtime stage ─────────────────────────────────────────────────────────────
16+
FROM node:24-slim AS runtime
17+
18+
RUN apt-get update && apt-get install -y --no-install-recommends \
19+
tini \
20+
&& rm -rf /var/lib/apt/lists/*
21+
22+
WORKDIR /app
23+
24+
# Copy the compiled bundle (no node_modules needed — no native deps)
25+
COPY --from=builder /app/dist ./dist
26+
27+
RUN mkdir -p /data
28+
29+
VOLUME ["/data"]
30+
31+
EXPOSE 3000
32+
33+
ENV NODE_ENV=production \
34+
DATA_DIR=/data \
35+
PORT=3000
36+
37+
# Use tini as PID 1 for proper signal handling
38+
ENTRYPOINT ["tini", "--"]
39+
CMD ["node", "dist/server.js"]

0 commit comments

Comments
 (0)