Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b81d88e
chore: support internal servers in registry processing
qstearns Mar 18, 2026
b4ce94d
chore: add clarifying comment
qstearns Mar 18, 2026
5c38fa5
wip
adaam2 Mar 17, 2026
3ed5726
feat: wire collections to real APIs, expand card UX, discover tab
adaam2 Mar 17, 2026
087c1dc
feat: fetch MCP servers from all projects in create collection
adaam2 Mar 17, 2026
78af160
fix: consistent card heights and grey bg in server picker
adaam2 Mar 17, 2026
9126d85
fix: extend grey bg to include title and search in server picker
adaam2 Mar 17, 2026
12c1ae0
fix: use blue tick for selected servers in collection picker
adaam2 Mar 17, 2026
baa15e7
fix: selected server card keeps white bg instead of grey tint
adaam2 Mar 17, 2026
73e1d03
fix: show explanation text for both public and private visibility
adaam2 Mar 17, 2026
95bf0a1
fix: remove blue border from selected server cards
adaam2 Mar 17, 2026
6cc90e3
feat: wire install collection to real evolveDeployment API
adaam2 Mar 17, 2026
3e658e3
fix: remove broken navigation from collection server cards
adaam2 Mar 17, 2026
34a70be
feat: track toolset slug and MCP URL in telemetry attributes (#1903)
tgmendes Mar 17, 2026
0370621
feat: add toolset_slug materialized column to ClickHouse (#1906)
tgmendes Mar 17, 2026
43c99f1
fix: mcp environments section shows wrong default when none attached …
simplesagar Mar 17, 2026
98bf9a8
chore: log auth checks in server (#1908)
disintegrator Mar 17, 2026
72c7130
feat: filter observability overview by toolset slug instead of URN pr…
tgmendes Mar 18, 2026
6fa7d25
chore: regenerate SDK after merge
adaam2 Mar 18, 2026
e8fd7eb
fix: remove stale go.sum entries after merge
adaam2 Mar 18, 2026
1ebef8a
improve the button
qstearns Mar 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/slow-sheep-care.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"dashboard": patch
---

fix: MCP environments section shows wrong default when none attached
190 changes: 190 additions & 0 deletions .claude/commands/dependabot-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
---
description: Review and process open Dependabot PRs with automated lint, test, changelog analysis, and approval workflow
---

# Dependabot PR Review

Automate the review of open Dependabot pull requests. For each PR: check out the branch, run lint/test, analyze the changelog against codebase usage, fix issues, and present a summary for approval.

## Step 1: Discover open Dependabot PRs

Run:
```
gh pr list --repo speakeasy-api/gram --author 'app/dependabot' --state open --json number,title,headRefName,url
```

If there are no open Dependabot PRs, inform the user and stop.

Display the list of discovered PRs to the user before proceeding.

## Step 2: Process PRs in parallel batches

Process PRs in batches of **3 at a time**. For each PR, spawn a sub-agent using the Agent tool with `isolation: "worktree"` and `subagent_type: "general-purpose"`.

Pass each sub-agent the following prompt (fill in the PR-specific values):

---

**You are reviewing Dependabot PR #NUMBER: "TITLE"**
**Branch:** BRANCH_NAME
**URL:** PR_URL

Activate the `golang` skill if this PR touches Go code.

### Tools available

This project uses `mise` as its task runner. Run `mise tasks` to discover available commands for linting, testing, building, and more. Use `mise run <task> --help` for details on any task.

### Setup

1. Fetch and check out the PR branch:
```
git fetch origin BRANCH_NAME
git checkout BRANCH_NAME
```

2. Identify what changed:
```
git diff main..HEAD --name-only
```

### Analyze dependency changes

1. Parse the diff to extract which dependencies changed and their old→new versions:
- For Go: diff `go.mod` between main and HEAD
- For npm: diff `package.json` files between main and HEAD
- For Docker: diff Dockerfiles between main and HEAD
- For GitHub Actions: diff `.github/workflows/` between main and HEAD

2. For each changed dependency, determine the GitHub repository (from the module path or package registry).

### Run lint and test (in parallel where possible)

Based on what files changed, run the appropriate checks:
- Go files changed → run `mise lint:server` and `mise test:server` in parallel (use parallel Bash calls)
- Client files changed → run `mise lint:client`
- CLI files changed → run `mise lint:cli`
- Functions files changed → run `mise lint:functions`

Record pass/fail for each.

### Fetch and analyze changelog

For each changed dependency:

1. **Try GitHub Releases first:**
```
gh api --method GET repos/{owner}/{repo}/releases --jq '.[].tag_name' 2>/dev/null
```
Filter releases between the old and new version tags. Fetch the body of relevant releases.

2. **Fall back to CHANGELOG.md:**
```
gh api --method GET repos/{owner}/{repo}/contents/CHANGELOG.md --jq '.content | @base64d' 2>/dev/null
```
Extract the section between old and new versions.

3. If neither works, record "no changelog found".

4. **Record the changelog URL** for each dependency — either the GitHub Releases page (`https://github.com/{owner}/{repo}/releases`) or a direct link to the CHANGELOG.md (`https://github.com/{owner}/{repo}/blob/main/CHANGELOG.md`).

### Analyze impact on our codebase

1. Search for all imports and usages of the changed dependency in our codebase:
- For Go: `grep -r "import_path" server/ cli/ functions/`
- For npm: grep for the package name in `client/` and `elements/`

2. Cross-reference changelog entries against our usage. Categorize the risk:
- **breaking**: A public API, type, function, or interface we import/use has changed, been removed, or had its signature modified
- **deprecation**: Something we use is marked deprecated
- **internal**: Changes are internal to the dependency and don't affect any API surface we consume
- **unknown**: No changelog available to assess

3. **Be conservative**: If we consume ANY interface, type, or function mentioned in the changelog — even if the change "shouldn't" affect our usage in principle — flag it as needing review. Err on the side of caution.

4. **Highlight opportunities**: Look for new features, APIs, or improvements in the changelog that could benefit our codebase. For example: new utility functions we could adopt, performance improvements we could opt into, or new configuration options that would be useful. Note these as `opportunities` in your result.

### Fix issues

If lint or tests fail:
- Attempt straightforward fixes (import path changes, renamed functions, updated API signatures)
- After making Go changes, run `mise run go:tidy` to clean up module dependencies
- Run `hk fix --all` to auto-fix formatting and lint issues
- **Do NOT commit or push.** Leave your changes staged/unstaged — the supervising agent will handle committing and pushing.
- If the fix is non-trivial or uncertain, do NOT attempt it — flag it for human review instead

### Return your findings

Return a **single structured summary** in exactly this format (the supervising agent will parse this):

```
DEPENDABOT_RESULT_START
pr_number: NUMBER
pr_title: TITLE
pr_url: URL
worktree_path: /path/to/worktree
branch: BRANCH_NAME
lint_passed: true/false
test_passed: true/false
fixes_committed: true/false
dependencies:
- name: DEPENDENCY_NAME
old_version: X.Y.Z
new_version: A.B.C
risk_tier: breaking/deprecation/internal/unknown
changelog_url: https://github.com/{owner}/{repo}/releases (or CHANGELOG.md link)
changelog_summary: One-line summary of changes
concerns:
- Specific concern about API/interface we consume
- Another concern
opportunities:
- New feature/API we could adopt and how it would help
our_usage:
- file:line where we import/use this dep
recommendation: approve/needs-review
recommendation_reason: Brief explanation
DEPENDABOT_RESULT_END
```

---

## Step 3: Compile results

After all sub-agents complete, compile their results into a summary table:

```
| # | PR | Dependency | Version | Lint | Test | Risk | Fixes | Recommendation |
|---|-----|------------|---------|------|------|------|-------|----------------|
```

Below the table:
- For each dependency, include a link to the changelog (GitHub Releases page or CHANGELOG.md).
- For any PR with `opportunities`, list them so the user can consider follow-up work.
- For any PR flagged `needs-review`, list the specific concerns.

## Step 4: User confirmation

Use AskUserQuestion with `multiSelect: true` to ask:
> "Which PRs should be approved and pushed?"

List each PR as an option with its recommendation. PRs marked `needs-review` should include "(Needs Review)" in their label.

## Step 5: Commit and push approved PRs

For each approved PR where the sub-agent made fixes:
1. Stage and commit changes from the worktree: `git -C <worktree_path> add -A && git -C <worktree_path> commit -m "fix: resolve compatibility issues with <dep> upgrade"`
2. Push to the PR branch: `git -C <worktree_path> push origin <branch>`
3. Output the PR URL for the user to merge

For PRs not approved, just note them as skipped.

## Step 6: Clean up all worktrees

After pushing (or skipping), remove ALL worktrees created during this process:
```
git worktree remove --force <worktree_path>
```

Do this for every worktree, whether the PR was approved or not.

Provide a final summary: how many PRs were pushed, how many skipped, and links to the pushed PRs.
78 changes: 78 additions & 0 deletions .claude/commands/poc-demo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
description: Collaborate on a proof-of-concept demo for a Linear feature ticket using frontend-only changes
---

# POC Demo

You are collaborating with the user to build a proof-of-concept that communicates a feature's value through interactive UI and screen recordings. No backend changes. No working system-level functionality. Just enough to see, feel, and discuss the feature.

The goal is to create alignment around vision _before_ changing how the system behaves.

## Artifacts to produce

1. A runnable frontend showing the feature interactions
2. Screen recordings showing common use cases (user records these; you help plan the scripts)
3. A checklist of screencast scripts (one per user journey) with starting states defined
4. The Linear ticket updated with journey sections, video placeholders, and discussion items
5. A Pull Request with the `preview` label, using the Linear ticket's preferred branch name

## Out of scope

- Scoping the actual engineering work or system changes needed to ship the feature
- Making changes to API surfaces or backend code
- Making builds pass

## Phase 1: Align on the feature

1. Get the Linear ticket from the user (use Linear MCP if available, otherwise ask them to paste it). Add the `poc` label to the ticket.
2. Read and internalize the ticket. Ask clarifying questions.
3. Identify all user journeys required to demonstrate the feature's value. Work with the user to enumerate them.
4. For each journey, produce a mermaid diagram and add it to the ticket.
5. If a journey assumes pre-existing system state (e.g. "user already has a project with 3 toolsets"), call that out explicitly. Add a checkbox to the ticket: "Verify onboarding to this starting state is acceptable."

Each journey gets its own section in the Linear ticket containing:

- Mermaid diagram of the workflow
- Placeholder for a video recording
- Discussion section with key product questions

## Phase 2: Build the frontend POC

**Rules:**

- Only change code in `client/dashboard/`
- Prioritize visual clarity of the concept over code quality
- Mock data however is easiest - hardcoded JSON, fake hooks, whatever gets you moving
- Use `docker-compose exec psql -c "<QUERY>"` to seed starting states; reference `server/database/schema.sql` for the schema
- Prompt the user to deploy sources if seed state is insufficient
- Aim for visual impact. Make the feature obvious and interactive.
- Prefer reusing existing UI and functionality to achieve a step in a journey over building something new. Identifying that an existing feature already covers a step is more valuable than implementing a new one.

**Process:**

1. Inspect the schema to understand what seed data you need
2. Set up starting states via SQL
3. Build the UI changes. Prefer fast iteration over clean abstractions.
4. Test each journey interactively with the user

## Phase 3: Define screencast scripts

For each user journey:

1. Define the exact starting state (SQL seeds, page to start on)
2. Write a step-by-step script: what to click, what to look for, what to narrate
3. If a UI element needs visual emphasis during the recording, add temporary CSS to highlight it
4. Align with the user on the script before they record

## Phase 4: Update the Linear ticket

1. Ensure every journey has its own section with: diagram, video placeholder, discussion items
2. Add a "Key product decisions" section capturing choices made during the POC
3. Add scope-reduction suggestions if any emerged during the work

## Phase 5: Open the PR

1. Use the Linear ticket's preferred branch name (e.g. `quinn/gram-1234-feature-name`)
2. Commit all changes and push
3. Open a PR with the `preview` label
4. Link the PR in the Linear ticket
38 changes: 38 additions & 0 deletions .claude/notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Architecture Notes

## Org vs Project Scoping (2026-03-12)

### Taxonomy

- `org/team` > `projects`
- Users can only be a member of one org (for now)

### Settings Scope Analysis

Settings are routed under `/:orgSlug/:projectSlug/settings`, implying project-level scoping, but the backend implementations almost universally use `authCtx.ActiveOrganizationID`. The `Gram-Project` header, when present, is only used for auth middleware resolution.

| Settings Area | Route | Actual Scope | Notes |
| --------------------- | -------------------- | ------------------ | ----------------------------------------------------------------------------------------- |
| Custom Domain | `/settings/domains` | **Org-scoped** | `repo.GetCustomDomainByOrganization` — UI says "one custom domain per organization" |
| API Keys | `/settings/api-keys` | **Org-scoped** | `repo.ListAPIKeysByOrganization` — Goa design doesn't even require `ProjectSlug` security |
| Billing | `/billing` | **Org-scoped** | `billingRepo.GetPeriodUsage`, `CreateCheckout`, `CreateCustomerSession` all use org ID |
| Logging & Telemetry | `/settings/logs` | **Org-scoped** | `productfeatures` service uses `authCtx.ActiveOrganizationID` for both get and set |
| Team | N/A | **Org-scoped** | No pages/endpoints exist yet — currently handled by Speakeasy IDP |
| General / Danger Zone | `/settings/general` | **Project-scoped** | Project deletion — the only genuinely project-level setting |

### Key Observations

1. Some org-scoped endpoints (domains, telemetry, billing) still declare `Security(security.Session, security.ProjectSlug)` in Goa design files, even though the project slug is only used for auth context resolution and ignored by service implementations.
2. This creates a misleading coupling — the frontend must select a project to access settings that have nothing to do with that project.
3. These settings could live under an org-level route (e.g. `/:orgSlug/settings/...`) without any backend changes, since the backend already treats them as org-scoped.

### Relevant Backend Files

- `server/internal/customdomains/impl.go`
- `server/internal/keys/impl.go`
- `server/internal/usage/impl.go`
- `server/internal/productfeatures/impl.go`
- `server/design/domains/design.go`
- `server/design/keys/design.go`
- `server/design/usage/design.go`
- `server/design/productfeatures/design.go`
1 change: 1 addition & 0 deletions .claude/skills/registry
51 changes: 51 additions & 0 deletions .mise-tasks/git/sync-common-config.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env bash

#MISE description="Sync common config files from the main worktree"
#MISE hide=true
#MISE alias="gscc"

#USAGE flag "-f --force" help="Sync even if destinations have uncommitted changes"

set -e

main_worktree=$(cd "$(git rev-parse --git-common-dir)/.." && pwd)
current_worktree=$(git rev-parse --show-toplevel)

if [ "$main_worktree" = "$current_worktree" ]; then
echo "Already in the main worktree, nothing to sync."
exit 0
fi

sync_items=(
.mise-tasks
.claude
.cursor
.vscode
local
mise.local.toml
)

if [ "${usage_force:-false}" != "true" ]; then
dirty=()
for item in "${sync_items[@]}"; do
if [ -n "$(git status --porcelain -- "$item" 2>/dev/null)" ]; then
dirty+=("$item")
fi
done
if [ ${#dirty[@]} -gt 0 ]; then
echo "The following paths have uncommitted changes:"
printf ' %s\n' "${dirty[@]}"
echo "Aborting sync. Use --force to override."
exit 1
fi
fi

for item in "${sync_items[@]}"; do
src="${main_worktree}/${item}"
if [ -e "$src" ]; then
echo "Syncing $item"
rsync -a "$src" "$current_worktree/"
fi
done

echo "Done."
Loading
Loading