Skip to content

Commit 6b82df5

Browse files
ofershapcursoragent
andcommitted
feat: add security infrastructure and rewrite README for enterprise trust
Add CodeQL scanning, OpenSSF Scorecard, Dependabot, SECURITY.md, CODE_OF_CONDUCT.md. Rewrite README with why/what narrative, security section, and OpenSSF Best Practices passing badge. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent aa11f3b commit 6b82df5

6 files changed

Lines changed: 294 additions & 40 deletions

File tree

.github/dependabot.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: npm
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
open-pull-requests-limit: 10
8+
groups:
9+
minor-and-patch:
10+
update-types:
11+
- minor
12+
- patch
13+
- package-ecosystem: github-actions
14+
directory: /
15+
schedule:
16+
interval: weekly
17+
open-pull-requests-limit: 5

.github/workflows/codeql.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: CodeQL
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
schedule:
9+
- cron: "0 6 * * 1"
10+
11+
permissions:
12+
security-events: write
13+
contents: read
14+
15+
jobs:
16+
analyze:
17+
runs-on: ubuntu-latest
18+
strategy:
19+
fail-fast: false
20+
matrix:
21+
language: [javascript-typescript]
22+
steps:
23+
- uses: actions/checkout@v4
24+
- uses: github/codeql-action/init@v3
25+
with:
26+
languages: ${{ matrix.language }}
27+
- uses: github/codeql-action/autobuild@v3
28+
- uses: github/codeql-action/analyze@v3
29+
with:
30+
category: "/language:${{ matrix.language }}"

.github/workflows/scorecard.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: OpenSSF Scorecard
2+
3+
on:
4+
push:
5+
branches: [main]
6+
schedule:
7+
- cron: "0 6 * * 1"
8+
9+
permissions: read-all
10+
11+
jobs:
12+
analysis:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
security-events: write
16+
id-token: write
17+
steps:
18+
- uses: actions/checkout@v4
19+
with:
20+
persist-credentials: false
21+
- uses: ossf/scorecard-action@v2.4.3
22+
with:
23+
results_file: results.sarif
24+
results_format: sarif
25+
publish_results: true
26+
- uses: actions/upload-artifact@v4
27+
with:
28+
name: SARIF file
29+
path: results.sarif
30+
retention-days: 5
31+
- uses: github/codeql-action/upload-sarif@v3
32+
with:
33+
sarif_file: results.sarif

CODE_OF_CONDUCT.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Contributor Covenant Code of Conduct
2+
3+
## Our Pledge
4+
5+
We as members, contributors, and leaders pledge to make participation in our
6+
community a harassment-free experience for everyone, regardless of age, body
7+
size, visible or invisible disability, ethnicity, sex characteristics, gender
8+
identity and expression, level of experience, education, socio-economic status,
9+
nationality, personal appearance, race, caste, color, religion, or sexual
10+
identity and orientation.
11+
12+
We pledge to act and interact in ways that contribute to an open, welcoming,
13+
diverse, inclusive, and healthy community.
14+
15+
## Our Standards
16+
17+
Examples of behavior that contributes to a positive environment for our
18+
community include:
19+
20+
- Demonstrating empathy and kindness toward other people
21+
- Being respectful of differing opinions, viewpoints, and experiences
22+
- Giving and gracefully accepting constructive feedback
23+
- Accepting responsibility and apologizing to those affected by our mistakes,
24+
and learning from the experience
25+
- Focusing on what is best not just for us as individuals, but for the overall
26+
community
27+
28+
Examples of unacceptable behavior include:
29+
30+
- The use of sexualized language or imagery, and sexual attention or advances of
31+
any kind
32+
- Trolling, insulting or derogatory comments, and personal or political attacks
33+
- Public or private harassment
34+
- Publishing others' private information, such as a physical or email address,
35+
without their explicit permission
36+
- Other conduct which could reasonably be considered inappropriate in a
37+
professional setting
38+
39+
## Enforcement Responsibilities
40+
41+
Community leaders are responsible for clarifying and enforcing our standards of
42+
acceptable behavior and will take appropriate and fair corrective action in
43+
response to any behavior that they deem inappropriate, threatening, offensive,
44+
or harmful.
45+
46+
Community leaders have the right and responsibility to remove, edit, or reject
47+
comments, commits, code, wiki edits, issues, and other contributions that are
48+
not aligned to this Code of Conduct, and will communicate reasons for moderation
49+
decisions when appropriate.
50+
51+
## Scope
52+
53+
This Code of Conduct applies within all community spaces, and also applies when
54+
an individual is officially representing the community in public spaces.
55+
Examples of representing our community include using an official email address,
56+
posting via an official social media account, or acting as an appointed
57+
representative at an online or offline event.
58+
59+
## Enforcement
60+
61+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
62+
reported to the community leaders responsible for enforcement at
63+
**<ofershapira@gmail.com>**.
64+
65+
All complaints will be reviewed and investigated promptly and fairly.
66+
67+
All community leaders are obligated to respect the privacy and security of the
68+
reporter of any incident.
69+
70+
## Attribution
71+
72+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
73+
version 2.1, available at
74+
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
75+
76+
[homepage]: https://www.contributor-covenant.org
77+
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html

README.md

Lines changed: 74 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,45 @@
55
<h1 align="center">Cursor Usage Tracker</h1>
66

77
<p align="center">
8+
AI spend monitoring, anomaly detection, and alerting for teams on Cursor Enterprise.<br>
9+
Know who's burning through your budget before the invoice tells you.
10+
</p>
11+
12+
<p align="center">
13+
<a href="https://github.com/ofershap/cursor-usage-tracker/actions/workflows/ci.yml"><img src="https://github.com/ofershap/cursor-usage-tracker/actions/workflows/ci.yml/badge.svg" alt="CI" /></a>
14+
<a href="https://github.com/ofershap/cursor-usage-tracker/actions/workflows/codeql.yml"><img src="https://github.com/ofershap/cursor-usage-tracker/actions/workflows/codeql.yml/badge.svg" alt="CodeQL" /></a>
15+
<a href="https://scorecard.dev/viewer/?uri=github.com/ofershap/cursor-usage-tracker"><img src="https://api.scorecard.dev/projects/github.com/ofershap/cursor-usage-tracker/badge" alt="OpenSSF Scorecard" /></a>
16+
<a href="https://www.bestpractices.dev/projects/11968"><img src="https://www.bestpractices.dev/projects/11968/badge" alt="OpenSSF Best Practices" /></a>
817
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT" /></a>
918
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-strict-blue" alt="TypeScript" /></a>
1019
<a href="https://www.docker.com/"><img src="https://img.shields.io/badge/Docker-ready-2496ED" alt="Docker" /></a>
1120
</p>
1221

13-
**Your company has 50+ developers on Cursor. Do you know who's spending $200/day on Claude Opus while everyone else uses Sonnet?**
22+
---
1423

15-
You're about to find out.
24+
## Why This Exists
1625

17-
![Demo](assets/demo.gif)
26+
Engineering costs used to be two things: headcount and cloud infrastructure. You had tools for both. Then AI coding assistants showed up, and suddenly there's a third cost center that nobody has good tooling for.
1827

19-
<sub>Demo animation created with <a href="https://github.com/ofershap/remotion-readme-kit">remotion-readme-kit</a></sub>
28+
A single developer on Cursor can burn through hundreds of dollars a day just by switching to an expensive model or letting an agent loop run wild. Now multiply that by 50, 100, 500 developers. The bill gets big fast, and there's nothing like Datadog or CloudHealth for this category yet.
29+
30+
Cursor's admin dashboard shows you the raw numbers, but it won't tell you when something is off. No anomaly detection. No alerts. No incident tracking. You find out about cost spikes when the invoice lands, weeks after the damage is done.
31+
32+
I built cursor-usage-tracker to fix that. It sits on top of Cursor's Enterprise APIs and gives engineering managers, finance, and platform teams actual visibility into AI spend before it becomes a surprise.
2033

2134
---
2235

23-
## The Problem
36+
## What It Does
2437

25-
You're managing Cursor for your engineering team. The bill comes in. It's... a lot.
38+
Your company has 50+ developers on Cursor. Do you know who's spending $200/day on Claude Opus while everyone else uses Sonnet?
2639

27-
- **Who** is driving the cost?
28-
- **When** did it start spiking?
29-
- **Why** — is it a model shift? A runaway agent? Legitimate heavy usage?
30-
- **How long** until someone notices?
40+
You're about to find out.
3141

32-
Cursor's built-in dashboard shows data, but has **no anomaly detection** and **no proactive alerting**. You find out about cost spikes when the invoice arrives — weeks too late.
42+
![Demo](assets/demo.gif)
3343

34-
## The Solution
44+
<sub>Demo animation created with <a href="https://github.com/ofershap/remotion-readme-kit">remotion-readme-kit</a></sub>
3545

36-
cursor-usage-tracker connects to Cursor's Enterprise APIs, collects usage data, and **automatically detects anomalies** across three layers of intelligence. When something looks off, you get a Slack message or email — not next month, but within the hour.
46+
It connects to Cursor's Enterprise APIs, collects usage data, and automatically detects anomalies across three layers. When something looks off, you get a Slack message or email within the hour, not next month.
3747

3848
```
3949
Developer uses Cursor → API collects data hourly → Engine detects anomaly → You get a Slack alert
@@ -49,7 +59,7 @@ Developer uses Cursor → API collects data hourly → Engine detects anomaly
4959
| Someone shifts to expensive models | `Opus usage jumped from 5% to 45%` → Slack alert |
5060
| Usage drifts above team P75 for days | `Above team P75 for 5 of last 6 days` → Slack alert |
5161

52-
Every alert includes **who**, **what model**, **how much**, and a **link to their dashboard page** for instant investigation.
62+
Every alert includes who, what model, how much, and a link to their dashboard page so you can investigate immediately.
5363

5464
---
5565

@@ -75,14 +85,14 @@ Anomaly Detected ──→ Alert Sent ──→ Acknowledged ──→ Resolved
7585
└────────────────── MTTR ─────────────────────────┘
7686
```
7787

78-
- **MTTD** Mean Time to Detect: how fast the system catches it
79-
- **MTTI** Mean Time to Identify: how fast a human acknowledges it
80-
- **MTTR** Mean Time to Resolve: how fast it's fixed
88+
- **MTTD** (Mean Time to Detect): how fast the system catches it
89+
- **MTTI** (Mean Time to Identify): how fast a human acknowledges it
90+
- **MTTR** (Mean Time to Resolve): how fast it gets fixed
8191

8292
### Rich Alerting
8393

84-
- **Slack** Block Kit messages with severity, user, model, value vs threshold, and dashboard links
85-
- **Email** HTML-formatted alerts with the same context
94+
- **Slack**: Block Kit messages with severity, user, model, value vs threshold, and dashboard links
95+
- **Email**: HTML-formatted alerts with the same context
8696

8797
### Web Dashboard
8898

@@ -174,9 +184,9 @@ After collecting data, run detection separately:
174184
npm run detect
175185
```
176186

177-
This analyzes the stored data against all three detection layers and sends alerts for any anomalies found.
187+
This runs the stored data through all three detection layers and sends alerts for anything it finds.
178188

179-
> **Note:** `npm run collect` only fetches data. `npm run detect` only runs detection. The cron endpoint (`POST /api/cron`) does both in one call.
189+
> `npm run collect` only fetches data. `npm run detect` only runs detection. The cron endpoint (`POST /api/cron`) does both in one call.
180190
181191
### 6. Set up recurring collection
182192

@@ -186,7 +196,7 @@ Trigger the cron endpoint hourly (via crontab, GitHub Actions, or any scheduler)
186196
curl -X POST http://localhost:3000/api/cron -H "x-cron-secret: YOUR_SECRET"
187197
```
188198

189-
This collects data, runs anomaly detection, and sends alerts — all in one call.
199+
This collects data, runs anomaly detection, and sends alerts in one call.
190200

191201
---
192202

@@ -229,9 +239,9 @@ flowchart TB
229239
APIs["Cursor Enterprise APIs\n/teams/members · /teams/spend · /teams/daily-usage-data\n/teams/filtered-usage-events · /teams/groups · /analytics/team/*"]
230240
C["Collector (hourly)"]
231241
DB[("SQLite (local)")]
232-
D["Detection Engine 3 layers"]
233-
AL["Alerts · Slack / Email"]
234-
DA["Dashboard · Next.js"]
242+
D["Detection Engine, 3 layers"]
243+
AL["Alerts: Slack / Email"]
244+
DA["Dashboard: Next.js"]
235245

236246
APIs --> C --> DB --> D
237247
DB --> DA
@@ -258,15 +268,16 @@ All detection thresholds are configurable via the Settings page or the API:
258268

259269
---
260270

261-
## Group Management & Filtering
271+
<details>
272+
<summary><strong>Billing Groups: organize teams by department, group, or custom structure</strong></summary>
262273

263274
Billing groups let you organize team members by department, team, or any structure that fits your org.
264275

265-
### Dashboard Filtering
276+
**Dashboard Filtering**
266277

267278
The Team Overview page includes a group filter dropdown next to the search bar. Select a group to instantly filter all stats, charts, and the members table to that subset. Groups are displayed in a hierarchical `Parent > Team` format.
268279

269-
### Settings Page
280+
**Settings Page**
270281

271282
From the Settings page you can:
272283

@@ -276,7 +287,10 @@ From the Settings page you can:
276287
- **Create** new groups manually
277288
- **Search** across all members to find who's in which group
278289

279-
### HiBob Import
290+
</details>
291+
292+
<details>
293+
<summary><strong>HiBob Import: sync your org structure from HiBob's People Directory</strong></summary>
280294

281295
For teams using [HiBob](https://www.hibob.com/) as their HR platform, the Settings page includes an **Import from HiBob** feature:
282296

@@ -287,7 +301,9 @@ For teams using [HiBob](https://www.hibob.com/) as their HR platform, the Settin
287301

288302
The import uses HiBob's `Group` and `Team` columns (falling back to `Department`) to build a `Group > Team` hierarchy. Small teams (fewer than 3 members) are automatically consolidated into broader groups to avoid excessive granularity.
289303

290-
> **Note:** The HiBob import updates your local billing groups. It does not push changes back to HiBob or to Cursor's billing API — it only organizes members within the tracker's dashboard.
304+
> The HiBob import updates your local billing groups only. It does not push changes back to HiBob or to Cursor's billing API.
305+
306+
</details>
291307

292308
---
293309

@@ -312,15 +328,15 @@ The import uses HiBob's `Group` and `Team` columns (falling back to `Department`
312328

313329
## Tech Stack
314330

315-
| Component | Technology |
316-
| ---------- | ------------------------------------- |
317-
| Framework | Next.js (App Router) |
318-
| Language | TypeScript (strict mode) |
319-
| Database | SQLite (better-sqlite3) zero config |
320-
| Charts | Recharts |
321-
| Styling | Tailwind CSS |
322-
| Testing | Vitest |
323-
| Deployment | Docker (multi-stage) |
331+
| Component | Technology |
332+
| ---------- | ------------------------------------ |
333+
| Framework | Next.js (App Router) |
334+
| Language | TypeScript (strict mode) |
335+
| Database | SQLite (better-sqlite3), zero config |
336+
| Charts | Recharts |
337+
| Styling | Tailwind CSS |
338+
| Testing | Vitest |
339+
| Deployment | Docker (multi-stage) |
324340

325341
---
326342

@@ -354,9 +370,27 @@ Rate limit: 20 requests/minute (Admin API), 100 requests/minute (Analytics API).
354370

355371
---
356372

373+
## Security
374+
375+
This project handles sensitive usage and spending data, so security matters here more than most.
376+
377+
- **Vulnerability reporting**: See [SECURITY.md](SECURITY.md) for the disclosure policy. Report vulnerabilities privately via [GitHub Security Advisories](https://github.com/ofershap/cursor-usage-tracker/security/advisories/new), not public issues.
378+
- **Automated scanning**: Every push and PR goes through [CodeQL](https://codeql.github.com/) (SQL injection, XSS, CSRF, etc.) and [Dependabot](https://docs.github.com/en/code-security/dependabot) for dependency vulnerabilities.
379+
- **OpenSSF Scorecard**: Continuously evaluated against [OpenSSF Scorecard](https://scorecard.dev/viewer/?uri=github.com/ofershap/cursor-usage-tracker) security benchmarks.
380+
- **OpenSSF Best Practices**: [Passing badge](https://www.bestpractices.dev/projects/11968) earned.
381+
- **Data stays local**: Everything is stored in a local SQLite file. Nothing leaves your infrastructure. No external databases, no cloud services, no telemetry.
382+
- **Small dependency tree**: Fewer dependencies = smaller attack surface.
383+
- **Signed releases**: Automated via semantic-release with GitHub-verified provenance.
384+
385+
---
386+
357387
## Contributing
358388

359-
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
389+
See [CONTRIBUTING.md](CONTRIBUTING.md) for setup and guidelines. Bug reports, feature requests, docs improvements, and code are all welcome. Use [conventional commits](https://www.conventionalcommits.org/) and make sure CI is green before opening a PR.
390+
391+
## Code of Conduct
392+
393+
This project uses the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md).
360394

361395
## Author
362396

0 commit comments

Comments
 (0)