From 2f17c9d1bf928986c9c2087ef29c04fdbe21e324 Mon Sep 17 00:00:00 2001 From: melkeydev Date: Thu, 30 Jul 2026 16:15:44 -0700 Subject: [PATCH 1/4] Adding new deployment protection skill --- README.md | 6 +- generated/skill-catalog.md | 15 +- generated/skill-manifest.json | 110 +++++++++++- .../SKILL.md | 161 ++++++++++++++++++ ...-protected-vercel-deployment-skill.test.ts | 112 ++++++++++++ vercel.md | 10 +- 6 files changed, 407 insertions(+), 7 deletions(-) create mode 100644 skills/access-protected-vercel-deployment/SKILL.md create mode 100644 tests/access-protected-vercel-deployment-skill.test.ts diff --git a/README.md b/README.md index aefe567..a5f4cd4 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,11 @@ A text-form relational graph covering: - Common cross-product workflows - Migration awareness for sunset products -### Skills (30 skills) +### Skills (31 skills) | Skill | Covers | | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | +| `access-protected-vercel-deployment` | Authenticated CLI and browser access to protected preview and production deployments using `vc curl`, OIDC, and Trusted Sources | | `ai-gateway` | Unified model API, provider routing, failover, cost tracking, 100+ models | | `ai-sdk` | AI SDK v6 — text/object generation, streaming, tool calling, agents, MCP, providers, embeddings | | `auth` | Authentication integrations — Clerk, Descope, Auth0 setup for Next.js with Marketplace provisioning | @@ -226,7 +227,7 @@ Exits non-zero if any `SKILL.md` is stale. Add to CI to catch drift. vercel-plugin/ ├── .plugin/plugin.json # Plugin manifest ├── vercel.md # Ecosystem graph + conventions (injected via SessionStart hook) -├── skills/ # 29 skills +├── skills/ # 31 skills │ ├── ai-sdk/ # Upstream-synced skill example: │ │ ├── overlay.yaml # Plugin injection metadata │ │ ├── upstream/ # Pure upstream content @@ -280,6 +281,7 @@ bun run build:from-skills # Stage 4: Resolve template includes - Turbopack (default bundler in Next.js 16) - v0 (agentic intelligence, GitHub integration) - Vercel CLI (cache management, MCP integration, marketplace discovery) +- Protected deployment access (`vc curl`, local OIDC tokens, Trusted Sources) - Vercel Observability (Analytics, Speed Insights, Drains) - Vercel Marketplace (one-click integrations, unified billing) - Agent Browser (browser automation for dev server verification and testing) diff --git a/generated/skill-catalog.md b/generated/skill-catalog.md index 18f15fc..f0422bb 100644 --- a/generated/skill-catalog.md +++ b/generated/skill-catalog.md @@ -1,8 +1,8 @@ # Skill Catalog > Auto-generated by `scripts/generate-catalog.ts` — do not edit manually. -> Generated: 2026-07-06T20:39:13.075Z -> Skills: 30 +> Generated: 2026-07-30T16:09:09.642Z +> Skills: 31 ## Table of Contents @@ -17,6 +17,7 @@ |-------|----------|---------------|---------------|-----------------| | `knowledge-update` | 10 | 1 | 0 | 0 | | `workflow` | 9 | 6 | 14 | 4 | +| `access-protected-vercel-deployment` | 8 | 0 | 4 | 0 | | `ai-sdk` | 8 | 27 | 11 | 2 | | `bootstrap` | 8 | 10 | 6 | 8 | | `chat-sdk` | 8 | 45 | 12 | 2 | @@ -88,6 +89,14 @@ **Matched examples:** - `lib/workflow/index.ts` (path) +#### `access-protected-vercel-deployment` (priority 8) + +**Bash patterns:** +- `\b(?:vercel|vc)\s+curl\b` +- `\b(?:curl|wget)\b[^\n]*\.vercel\.app\b` +- `\bagent-browser\b[^\n]*(?:open|navigate|goto)[^\n]*\.vercel\.app\b` +- `\bx-vercel-trusted-oidc-idp-token\b` + #### `ai-sdk` (priority 8) **Path patterns:** @@ -959,7 +968,7 @@ Shows which skills compete on shared bash commands. **Priority 9:** `workflow` -**Priority 8:** `ai-sdk`, `bootstrap`, `chat-sdk`, `eve`, `vercel-functions` +**Priority 8:** `access-protected-vercel-deployment`, `ai-sdk`, `bootstrap`, `chat-sdk`, `eve`, `vercel-functions` **Priority 7:** `ai-gateway`, `env-vars`, `microfrontends`, `vercel-firewall`, `vercel-storage`, `verification` diff --git a/generated/skill-manifest.json b/generated/skill-manifest.json index bfab66c..8f8cdbb 100644 --- a/generated/skill-manifest.json +++ b/generated/skill-manifest.json @@ -1,7 +1,115 @@ { - "generatedAt": "2026-07-24T23:01:08.971Z", + "generatedAt": "2026-07-30T16:09:08.831Z", "version": 2, "skills": { + "access-protected-vercel-deployment": { + "priority": 8, + "summary": "Access protected Vercel URLs with vercel curl or a short-lived OIDC token", + "docs": [ + "https://vercel.com/docs/cli/curl", + "https://vercel.com/docs/deployment-protection/methods-to-bypass-deployment-protection/trusted-sources", + "https://vercel.com/docs/oidc#in-local-development" + ], + "sitemap": "https://vercel.com/sitemap/docs.xml", + "pathPatterns": [], + "bashPatterns": [ + "\\b(?:vercel|vc)\\s+curl\\b", + "\\b(?:curl|wget)\\b[^\\n]*\\.vercel\\.app\\b", + "\\bagent-browser\\b[^\\n]*(?:open|navigate|goto)[^\\n]*\\.vercel\\.app\\b", + "\\bx-vercel-trusted-oidc-idp-token\\b" + ], + "importPatterns": [], + "bodyPath": "skills/access-protected-vercel-deployment/SKILL.md", + "pathRegexSources": [], + "bashRegexSources": [ + "\\b(?:vercel|vc)\\s+curl\\b", + "\\b(?:curl|wget)\\b[^\\n]*\\.vercel\\.app\\b", + "\\bagent-browser\\b[^\\n]*(?:open|navigate|goto)[^\\n]*\\.vercel\\.app\\b", + "\\bx-vercel-trusted-oidc-idp-token\\b" + ], + "importRegexSources": [], + "promptSignals": { + "phrases": [ + "access protected vercel deployment", + "protected vercel deployment", + "deployment protection", + "vercel sso", + "vercel authentication page", + "behind vercel authentication", + "behind vercel sso", + "x-vercel-trusted-oidc-idp-token", + "trusted_sources_environment_mismatch", + "trusted sources environment mismatch", + "protection bypass" + ], + "allOf": [ + [ + "vercel", + "protected" + ], + [ + "vercel", + "sso" + ], + [ + "vercel", + "403" + ], + [ + "deployment", + "login" + ], + [ + "preview", + "protected" + ], + [ + "production", + "protected" + ] + ], + "anyOf": [ + "deployment", + "preview", + "production", + "curl", + "browser", + "authentication" + ], + "noneOf": [ + "aws deployment protection", + "github deployment protection", + "kubernetes deployment protection" + ], + "minScore": 6 + }, + "retrieval": { + "aliases": [ + "protected Vercel deployment", + "Vercel SSO bypass", + "Vercel deployment authentication", + "Vercel Trusted Sources" + ], + "intents": [ + "access a protected deployment", + "test a protected preview", + "verify a protected production deployment", + "authenticate browser automation to Vercel" + ], + "entities": [ + "vercel curl", + "VERCEL_OIDC_TOKEN", + "x-vercel-trusted-oidc-idp-token", + "Trusted Sources", + "Deployment Protection" + ], + "examples": [ + "preview is behind Vercel SSO", + "curl this protected Vercel deployment", + "open the protected production URL in agent-browser" + ] + } + }, "ai-gateway": { "priority": 7, "summary": "", diff --git a/skills/access-protected-vercel-deployment/SKILL.md b/skills/access-protected-vercel-deployment/SKILL.md new file mode 100644 index 0000000..b455845 --- /dev/null +++ b/skills/access-protected-vercel-deployment/SKILL.md @@ -0,0 +1,161 @@ +--- +name: access-protected-vercel-deployment +description: Access and test Vercel deployments protected by Vercel Authentication, SSO, or Deployment Protection. Use when curl, agent-browser, Playwright, or another automated request reaches a Vercel login or protection page; when a protected preview or production URL returns 401 or 403; when TRUSTED_SOURCES_ENVIRONMENT_MISMATCH appears; or when choosing between `vercel curl` and the `x-vercel-trusted-oidc-idp-token` header. +summary: Access protected Vercel URLs with vercel curl or a short-lived OIDC token +metadata: + priority: 8 + docs: + - "https://vercel.com/docs/cli/curl" + - "https://vercel.com/docs/deployment-protection/methods-to-bypass-deployment-protection/trusted-sources" + - "https://vercel.com/docs/oidc#in-local-development" + sitemap: "https://vercel.com/sitemap/docs.xml" + pathPatterns: [] + bashPatterns: + - '\b(?:vercel|vc)\s+curl\b' + - '\b(?:curl|wget)\b[^\n]*\.vercel\.app\b' + - '\bagent-browser\b[^\n]*(?:open|navigate|goto)[^\n]*\.vercel\.app\b' + - '\bx-vercel-trusted-oidc-idp-token\b' + importPatterns: [] + promptSignals: + phrases: + - "access protected vercel deployment" + - "protected vercel deployment" + - "deployment protection" + - "vercel sso" + - "vercel authentication page" + - "behind vercel authentication" + - "behind vercel sso" + - "x-vercel-trusted-oidc-idp-token" + - "trusted_sources_environment_mismatch" + - "trusted sources environment mismatch" + - "protection bypass" + allOf: + - [vercel, protected] + - [vercel, sso] + - [vercel, "403"] + - [deployment, login] + - [preview, protected] + - [production, protected] + anyOf: + - "deployment" + - "preview" + - "production" + - "curl" + - "browser" + - "authentication" + noneOf: + - "aws deployment protection" + - "github deployment protection" + - "kubernetes deployment protection" + minScore: 6 +retrieval: + aliases: + - protected Vercel deployment + - Vercel SSO bypass + - Vercel deployment authentication + - Vercel Trusted Sources + intents: + - access a protected deployment + - test a protected preview + - verify a protected production deployment + - authenticate browser automation to Vercel + entities: + - vercel curl + - VERCEL_OIDC_TOKEN + - x-vercel-trusted-oidc-idp-token + - Trusted Sources + - Deployment Protection + examples: + - preview is behind Vercel SSO + - curl this protected Vercel deployment + - open the protected production URL in agent-browser +--- + +# Access Protected Vercel Deployments + +Use the caller's existing Vercel authentication. Do not disable Deployment Protection or ask for a long-lived bypass secret as the first solution. + +## Choose the access path + +### HTTP requests: use `vercel curl` + +For response bodies, headers, health checks, and API calls, replace raw `curl` with `vercel curl` (`vc curl`). It accepts native curl options and uses Vercel authentication to access protected preview and production deployments. + +```bash +vc curl https://my-app.vercel.app/api/health +vc curl my-app.vercel.app/api/users -X POST \ + -H "Content-Type: application/json" \ + -d '{"name":"Ada"}' +vc curl /api/health +``` + +The path-only form targets the linked project's production deployment. Pass a full URL when the exact deployment matters. + +If authentication fails, check the local identity and project before changing protection settings: + +```bash +vc whoami +``` + +Inspect `.vercel/project.json` to confirm the linked project and team. Run `vc link` only when the directory is not linked or is linked to the wrong project. Run `vc login` only when the CLI reports that no authenticated user is available. + +### Browser automation: attach the development OIDC token + +Browser requests must include the short-lived local token as: + +```text +x-vercel-trusted-oidc-idp-token: +``` + +Use a browser tool that supports origin-scoped request headers. With `agent-browser`, inject development variables without printing or persisting the token: + +```bash +vc env run -- sh -c \ + 'test -n "$VERCEL_OIDC_TOKEN" && agent-browser open "$1" --headers "{\"x-vercel-trusted-oidc-idp-token\":\"$VERCEL_OIDC_TOKEN\"}"' \ + sh https://my-app.vercel.app +``` + +Then continue the normal browser workflow in the same session. For Playwright or another browser driver, set the same header in the browser context's extra HTTP headers before the first navigation. + +If the local CLI version does not provide the token through `vc env run`, refresh local development credentials with: + +```bash +vc env pull .env.local --yes +``` + +Load the file through the project's existing dotenv mechanism. Never print the token, paste its value into source code, or commit `.env.local`. + +Use `x-vercel-trusted-oidc-idp-token` for Trusted Sources. Do not substitute `x-vercel-oidc-token`; that header carries an OIDC token into a Vercel Function and serves a different purpose. + +## Trusted Sources rules + +A local development token for a linked Vercel project can access that same project's deployments by default. Do not ask the user to configure Trusted Sources for the normal same-project case. + +Configuration is needed when: + +- the caller belongs to another Vercel project or team; +- the target project's self-access rules were customized; or +- the response is `TRUSTED_SOURCES_ENVIRONMENT_MISMATCH`. + +In the target project, open **Settings → Deployment Protection → Trusted Sources**. Add or edit the caller and allow the required `from` → `to` environment pair. A local token has the `development` environment, so browser access to protected production may require `development` → `production`. + +Treat this as an access-control change: explain the exact rule required and obtain authorization before changing it. Do not broaden unrelated environment pairs. + +## Diagnose the response + +- A Vercel login, SSO, or Deployment Protection page means the request did not use an accepted authentication path. +- `TRUSTED_SOURCES_ENVIRONMENT_MISMATCH` means the token is valid but its caller environment is not allowed to reach the target environment. +- An application-generated `401` or `403` after Vercel protection is bypassed belongs to the application's own authentication and must be debugged separately. +- A deployment marked `"target": "production"` can still be protected. Do not assume production is public. + +## Avoid + +- Do not disable Deployment Protection to make automation pass. +- Do not send raw unauthenticated `curl` repeatedly after receiving the protection page. +- Do not start an interactive SSO browser login when `vc curl` or an origin-scoped OIDC header can authenticate the request. +- Do not expose `VERCEL_OIDC_TOKEN` in logs, screenshots, committed files, or user-facing output. + +## Related skills + +- General Vercel CLI usage: `⤳ skill: vercel-cli` +- End-to-end application verification: `⤳ skill: verification` diff --git a/tests/access-protected-vercel-deployment-skill.test.ts b/tests/access-protected-vercel-deployment-skill.test.ts new file mode 100644 index 0000000..9bb89bb --- /dev/null +++ b/tests/access-protected-vercel-deployment-skill.test.ts @@ -0,0 +1,112 @@ +import { beforeAll, describe, expect, test } from "bun:test"; +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import { + compileSkillPatterns, + matchBashWithReason, + type CompiledSkillEntry, +} from "../hooks/src/patterns.mts"; +import { + compilePromptSignals, + matchPromptWithReason, + normalizePromptText, + type CompiledPromptSignals, +} from "../hooks/src/prompt-patterns.mts"; +import { loadValidatedSkillMap } from "../src/shared/skill-map-loader.ts"; + +const ROOT = resolve(import.meta.dirname, ".."); +const SKILL_PATH = resolve( + ROOT, + "skills/access-protected-vercel-deployment/SKILL.md", +); + +let compiledPromptSignals: CompiledPromptSignals; +let compiledSkill: CompiledSkillEntry; + +beforeAll(() => { + const { skills } = loadValidatedSkillMap(resolve(ROOT, "skills")); + const protectedDeployment = skills["access-protected-vercel-deployment"]; + + expect(protectedDeployment).toBeDefined(); + expect(protectedDeployment.priority).toBe(8); + expect(protectedDeployment.promptSignals).toBeDefined(); + expect(protectedDeployment.promptSignals!.allOf).toContainEqual([ + "vercel", + "403", + ]); + + compiledPromptSignals = compilePromptSignals( + protectedDeployment.promptSignals!, + ); + compiledSkill = compileSkillPatterns({ + "access-protected-vercel-deployment": protectedDeployment, + })[0]; +}); + +function matchesPrompt(prompt: string): boolean { + return matchPromptWithReason( + normalizePromptText(prompt), + compiledPromptSignals, + ).matched; +} + +describe("protected deployment prompt activation", () => { + test.each([ + "Access this protected Vercel deployment.", + "Preview is behind Vercel SSO deployment protection.", + "The Vercel authentication page appears instead of the app.", + "curl gets a 403 from this Vercel deployment.", + "Open the protected production deployment in the browser.", + "Fix TRUSTED_SOURCES_ENVIRONMENT_MISMATCH.", + "Use x-vercel-trusted-oidc-idp-token for this request.", + ])("matches protected Vercel access intent: %s", (prompt) => { + expect(matchesPrompt(prompt)).toBe(true); + }); + + test.each([ + "Add authentication to my application.", + "Protect this Next.js route with Clerk.", + "Explain AWS deployment protection.", + "Run curl against localhost.", + "My Kubernetes deployment is protected by a pod disruption budget.", + ])("does not match unrelated protection or authentication intent: %s", (prompt) => { + expect(matchesPrompt(prompt)).toBe(false); + }); +}); + +describe("protected deployment command activation", () => { + test.each([ + "vc curl https://my-app.vercel.app/api/health", + "vercel curl /api/health", + "curl -I https://my-app-git-main.vercel.app", + "agent-browser open https://my-app.vercel.app", + "curl -H 'x-vercel-trusted-oidc-idp-token: token' https://example.com", + ])("matches protected deployment access commands: %s", (command) => { + expect( + matchBashWithReason(command, compiledSkill.compiledBash), + ).not.toBeNull(); + }); + + test.each([ + "curl http://localhost:3000", + "agent-browser open https://example.com", + "vercel logs", + "kubectl get deployments", + ])("does not match unrelated commands: %s", (command) => { + expect(matchBashWithReason(command, compiledSkill.compiledBash)).toBeNull(); + }); +}); + +describe("protected deployment guidance", () => { + test("documents both CLI and browser authentication paths", () => { + const skill = readFileSync(SKILL_PATH, "utf8"); + + expect(skill).toContain("vc curl"); + expect(skill).toContain("VERCEL_OIDC_TOKEN"); + expect(skill).toContain("x-vercel-trusted-oidc-idp-token"); + expect(skill).toContain("agent-browser"); + expect(skill).toContain("same project's deployments by default"); + expect(skill).toContain("development` → `production"); + expect(skill).toContain("Do not disable Deployment Protection"); + }); +}); diff --git a/vercel.md b/vercel.md index e760184..59167c4 100644 --- a/vercel.md +++ b/vercel.md @@ -1,4 +1,4 @@ -# Vercel Ecosystem — Relational Knowledge Graph (as of Mar 4, 2026) +# Vercel Ecosystem — Relational Knowledge Graph (as of Jul 30, 2026) > This document is the master reference for understanding the entire Vercel ecosystem. > It maps every product, library, CLI, API, and service — how they relate, when to use each, @@ -29,6 +29,8 @@ VERCEL PLATFORM 📖 docs: https://vercel.com/docs │ → Build System (Turbopack or framework-native) │ ↔ Vercel CLI │ ↔ Vercel REST API / @vercel/sdk +│ ⊃ Deployment Protection (Vercel Authentication, SSO, Trusted Sources) +│ ⤳ skill: access-protected-vercel-deployment │ ⤳ skill: vercel-cli │ ⤳ skill: deployments-cicd │ @@ -522,6 +524,12 @@ VERCEL CLI (vercel / vc) ⤳ skill: vercel-cli 📖 docs: htt │ ⊃ vercel deploy --prebuilt (deploy build output only) │ ⊃ vercel promote / vercel rollback │ +├── Protected Deployment Access ⤳ skill: access-protected-vercel-deployment +│ ⊃ vercel curl (authenticated HTTP requests to preview or production) +│ ⊃ VERCEL_OIDC_TOKEN (short-lived local development identity) +│ ⊃ x-vercel-trusted-oidc-idp-token (browser and automation requests) +│ ↔ Trusted Sources (caller project and environment access rules) +│ ├── Development │ ⊃ vercel dev (local dev server) │ ⊃ vercel link (connect to Vercel project) From 237f1eb5231906c6f5036202153f65bb4d794129 Mon Sep 17 00:00:00 2001 From: melkeydev Date: Thu, 30 Jul 2026 16:24:06 -0700 Subject: [PATCH 2/4] bumping plugin versoin --- .claude-plugin/plugin.json | 2 +- .cursor-plugin/plugin.json | 2 +- .kimi-plugin/plugin.json | 2 +- .plugin/plugin.json | 2 +- hooks/telemetry.mjs | 2 +- package.json | 2 +- tests/telemetry.test.ts | 4 ++-- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 62c8c1e..9d8dac2 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "vercel", - "version": "0.45.1", + "version": "0.46.0", "description": "Build and deploy web apps and agents", "author": { "name": "Vercel", diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json index 1eba763..68b828b 100644 --- a/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "vercel", - "version": "0.45.1", + "version": "0.46.0", "description": "Build and deploy web apps and agents", "author": { "name": "Vercel", diff --git a/.kimi-plugin/plugin.json b/.kimi-plugin/plugin.json index d301957..56d4278 100644 --- a/.kimi-plugin/plugin.json +++ b/.kimi-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "vercel-plugin", - "version": "0.45.1", + "version": "0.46.0", "description": "Comprehensive Vercel ecosystem plugin — relational knowledge graph, skills for every major product, specialized agents, and Vercel conventions. Turns any AI agent into a Vercel expert.", "keywords": [ "vercel", diff --git a/.plugin/plugin.json b/.plugin/plugin.json index 5380024..510de2f 100644 --- a/.plugin/plugin.json +++ b/.plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "vercel-plugin", - "version": "0.45.1", + "version": "0.46.0", "description": "Comprehensive Vercel ecosystem plugin — relational knowledge graph, skills for every major product, specialized agents, and Vercel conventions. Turns any AI agent into a Vercel expert.", "author": { "name": "Vercel", diff --git a/hooks/telemetry.mjs b/hooks/telemetry.mjs index 20dfdd7..44736f1 100644 --- a/hooks/telemetry.mjs +++ b/hooks/telemetry.mjs @@ -5,7 +5,7 @@ import { join, dirname } from "path"; import { homedir } from "os"; var BRIDGE_ENDPOINT = "https://telemetry.vercel.com/api/vercel-plugin/v1/events"; var FLUSH_TIMEOUT_MS = 3e3; -var PLUGIN_VERSION = true ? "0.45.1" : "0.43.0"; +var PLUGIN_VERSION = true ? "0.46.0" : "0.43.0"; var ACTIVE_SESSION_TTL_MS = 60 * 60 * 1e3; var DAU_STAMP_PATH = join(homedir(), ".config", "vercel-plugin", "dau-stamp"); var FIRST_USE_STAMP_PATH = join(homedir(), ".config", "vercel-plugin", "first-use-stamp"); diff --git a/package.json b/package.json index f0bbe40..180dbfd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vercel-plugin", - "version": "0.45.1", + "version": "0.46.0", "private": true, "license": "Apache-2.0", "bin": { diff --git a/tests/telemetry.test.ts b/tests/telemetry.test.ts index 63909dd..e435135 100644 --- a/tests/telemetry.test.ts +++ b/tests/telemetry.test.ts @@ -115,7 +115,7 @@ describe("telemetry controls", () => { expect(result.activeSessionMarker).toEqual({ schema: 1, active: true, - pluginVersion: "0.45.1", + pluginVersion: "0.46.0", updatedAt: Date.parse("2026-05-15T12:00:00.000Z"), expiresAt: Date.parse("2026-05-15T13:00:00.000Z"), }); @@ -131,7 +131,7 @@ describe("telemetry controls", () => { }), expect.objectContaining({ key: "plugin:version", - value: "0.45.1", + value: "0.46.0", }), ], ]); From 4be3b0d5dfd1c658be19fbd2d46b5490a7944843 Mon Sep 17 00:00:00 2001 From: melkeydev Date: Fri, 31 Jul 2026 09:12:26 -0700 Subject: [PATCH 3/4] fixing token access preview --- generated/skill-manifest.json | 2 +- skills/access-protected-vercel-deployment/SKILL.md | 7 +++++-- tests/access-protected-vercel-deployment-skill.test.ts | 6 +++++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/generated/skill-manifest.json b/generated/skill-manifest.json index 8f8cdbb..fff8d1c 100644 --- a/generated/skill-manifest.json +++ b/generated/skill-manifest.json @@ -1,5 +1,5 @@ { - "generatedAt": "2026-07-30T16:09:08.831Z", + "generatedAt": "2026-07-31T15:49:37.107Z", "version": 2, "skills": { "access-protected-vercel-deployment": { diff --git a/skills/access-protected-vercel-deployment/SKILL.md b/skills/access-protected-vercel-deployment/SKILL.md index b455845..03ea834 100644 --- a/skills/access-protected-vercel-deployment/SKILL.md +++ b/skills/access-protected-vercel-deployment/SKILL.md @@ -129,15 +129,18 @@ Use `x-vercel-trusted-oidc-idp-token` for Trusted Sources. Do not substitute `x- ## Trusted Sources rules -A local development token for a linked Vercel project can access that same project's deployments by default. Do not ask the user to configure Trusted Sources for the normal same-project case. +A local development token for a linked Vercel project can access that same project's Preview deployments by default. It does not automatically access protected Production deployments. For protected Production, the project's own Trusted Sources entry must allow `development` → `production`. + +Do not ask the user to configure Trusted Sources for the normal same-project Preview case. Configuration is needed when: +- the target is a protected Production deployment and the caller uses a local development token; - the caller belongs to another Vercel project or team; - the target project's self-access rules were customized; or - the response is `TRUSTED_SOURCES_ENVIRONMENT_MISMATCH`. -In the target project, open **Settings → Deployment Protection → Trusted Sources**. Add or edit the caller and allow the required `from` → `to` environment pair. A local token has the `development` environment, so browser access to protected production may require `development` → `production`. +In the target project, open **Settings → Deployment Protection → Trusted Sources**. Add or edit the caller and allow the required `from` → `to` environment pair. A local token has the `development` environment, so access to protected Production requires `development` → `production`. Treat this as an access-control change: explain the exact rule required and obtain authorization before changing it. Do not broaden unrelated environment pairs. diff --git a/tests/access-protected-vercel-deployment-skill.test.ts b/tests/access-protected-vercel-deployment-skill.test.ts index 9bb89bb..3422ac2 100644 --- a/tests/access-protected-vercel-deployment-skill.test.ts +++ b/tests/access-protected-vercel-deployment-skill.test.ts @@ -105,7 +105,11 @@ describe("protected deployment guidance", () => { expect(skill).toContain("VERCEL_OIDC_TOKEN"); expect(skill).toContain("x-vercel-trusted-oidc-idp-token"); expect(skill).toContain("agent-browser"); - expect(skill).toContain("same project's deployments by default"); + expect(skill).toContain("same project's Preview deployments by default"); + expect(skill).toContain( + "does not automatically access protected Production deployments", + ); + expect(skill).not.toContain("same project's deployments by default"); expect(skill).toContain("development` → `production"); expect(skill).toContain("Do not disable Deployment Protection"); }); From b93eb522b6f685ca776a6124b86807a04be7f6a1 Mon Sep 17 00:00:00 2001 From: melkeydev Date: Fri, 31 Jul 2026 11:16:35 -0700 Subject: [PATCH 4/4] fixing skill to have header and request header --- generated/skill-catalog.md | 4 ++-- generated/skill-manifest.json | 7 ++++--- skills/access-protected-vercel-deployment/SKILL.md | 11 ++++++++--- ...access-protected-vercel-deployment-skill.test.ts | 13 ++++++++++++- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/generated/skill-catalog.md b/generated/skill-catalog.md index f0422bb..1074e60 100644 --- a/generated/skill-catalog.md +++ b/generated/skill-catalog.md @@ -1,7 +1,7 @@ # Skill Catalog > Auto-generated by `scripts/generate-catalog.ts` — do not edit manually. -> Generated: 2026-07-30T16:09:09.642Z +> Generated: 2026-07-31T16:50:47.870Z > Skills: 31 ## Table of Contents @@ -95,7 +95,7 @@ - `\b(?:vercel|vc)\s+curl\b` - `\b(?:curl|wget)\b[^\n]*\.vercel\.app\b` - `\bagent-browser\b[^\n]*(?:open|navigate|goto)[^\n]*\.vercel\.app\b` -- `\bx-vercel-trusted-oidc-idp-token\b` +- `\bx-vercel-(?:trusted-oidc-idp-token|protection-bypass)\b` #### `ai-sdk` (priority 8) diff --git a/generated/skill-manifest.json b/generated/skill-manifest.json index fff8d1c..170937b 100644 --- a/generated/skill-manifest.json +++ b/generated/skill-manifest.json @@ -1,5 +1,5 @@ { - "generatedAt": "2026-07-31T15:49:37.107Z", + "generatedAt": "2026-07-31T18:16:05.834Z", "version": 2, "skills": { "access-protected-vercel-deployment": { @@ -16,7 +16,7 @@ "\\b(?:vercel|vc)\\s+curl\\b", "\\b(?:curl|wget)\\b[^\\n]*\\.vercel\\.app\\b", "\\bagent-browser\\b[^\\n]*(?:open|navigate|goto)[^\\n]*\\.vercel\\.app\\b", - "\\bx-vercel-trusted-oidc-idp-token\\b" + "\\bx-vercel-(?:trusted-oidc-idp-token|protection-bypass)\\b" ], "importPatterns": [], "bodyPath": "skills/access-protected-vercel-deployment/SKILL.md", @@ -25,7 +25,7 @@ "\\b(?:vercel|vc)\\s+curl\\b", "\\b(?:curl|wget)\\b[^\\n]*\\.vercel\\.app\\b", "\\bagent-browser\\b[^\\n]*(?:open|navigate|goto)[^\\n]*\\.vercel\\.app\\b", - "\\bx-vercel-trusted-oidc-idp-token\\b" + "\\bx-vercel-(?:trusted-oidc-idp-token|protection-bypass)\\b" ], "importRegexSources": [], "promptSignals": { @@ -106,6 +106,7 @@ "examples": [ "preview is behind Vercel SSO", "curl this protected Vercel deployment", + "access a protected Vercel deployment through a custom domain", "open the protected production URL in agent-browser" ] } diff --git a/skills/access-protected-vercel-deployment/SKILL.md b/skills/access-protected-vercel-deployment/SKILL.md index 03ea834..1f3605b 100644 --- a/skills/access-protected-vercel-deployment/SKILL.md +++ b/skills/access-protected-vercel-deployment/SKILL.md @@ -11,10 +11,13 @@ metadata: sitemap: "https://vercel.com/sitemap/docs.xml" pathPatterns: [] bashPatterns: + # Match vc curl for every hostname, including custom aliases. - '\b(?:vercel|vc)\s+curl\b' + # Keep raw clients scoped to hostnames that identify themselves as Vercel. - '\b(?:curl|wget)\b[^\n]*\.vercel\.app\b' - '\bagent-browser\b[^\n]*(?:open|navigate|goto)[^\n]*\.vercel\.app\b' - - '\bx-vercel-trusted-oidc-idp-token\b' + # Match custom aliases when the request includes an explicit Vercel protection header. + - '\bx-vercel-(?:trusted-oidc-idp-token|protection-bypass)\b' importPatterns: [] promptSignals: phrases: @@ -68,6 +71,7 @@ retrieval: examples: - preview is behind Vercel SSO - curl this protected Vercel deployment + - access a protected Vercel deployment through a custom domain - open the protected production URL in agent-browser --- @@ -83,6 +87,7 @@ For response bodies, headers, health checks, and API calls, replace raw `curl` w ```bash vc curl https://my-app.vercel.app/api/health +vc curl https://app.example.com/api/health vc curl my-app.vercel.app/api/users -X POST \ -H "Content-Type: application/json" \ -d '{"name":"Ada"}' @@ -99,9 +104,9 @@ vc whoami Inspect `.vercel/project.json` to confirm the linked project and team. Run `vc link` only when the directory is not linked or is linked to the wrong project. Run `vc login` only when the CLI reports that no authenticated user is available. -### Browser automation: attach the development OIDC token +### Browser automation: attach the development OIDC token as a header -Browser requests must include the short-lived local token as: +Browser requests must include the short-lived local token as a request header: ```text x-vercel-trusted-oidc-idp-token: diff --git a/tests/access-protected-vercel-deployment-skill.test.ts b/tests/access-protected-vercel-deployment-skill.test.ts index 3422ac2..b7c2ce4 100644 --- a/tests/access-protected-vercel-deployment-skill.test.ts +++ b/tests/access-protected-vercel-deployment-skill.test.ts @@ -57,6 +57,7 @@ describe("protected deployment prompt activation", () => { "The Vercel authentication page appears instead of the app.", "curl gets a 403 from this Vercel deployment.", "Open the protected production deployment in the browser.", + "My protected Vercel deployment uses a custom domain.", "Fix TRUSTED_SOURCES_ENVIRONMENT_MISMATCH.", "Use x-vercel-trusted-oidc-idp-token for this request.", ])("matches protected Vercel access intent: %s", (prompt) => { @@ -77,10 +78,13 @@ describe("protected deployment prompt activation", () => { describe("protected deployment command activation", () => { test.each([ "vc curl https://my-app.vercel.app/api/health", + "vc curl https://app.example.com/api/health", "vercel curl /api/health", + "vercel curl https://preview.example.com/api/health", "curl -I https://my-app-git-main.vercel.app", "agent-browser open https://my-app.vercel.app", - "curl -H 'x-vercel-trusted-oidc-idp-token: token' https://example.com", + "curl -H 'x-vercel-trusted-oidc-idp-token: token' https://app.example.com", + "curl -H 'x-vercel-protection-bypass: token' https://app.example.com", ])("matches protected deployment access commands: %s", (command) => { expect( matchBashWithReason(command, compiledSkill.compiledBash), @@ -89,6 +93,7 @@ describe("protected deployment command activation", () => { test.each([ "curl http://localhost:3000", + "curl https://api.example.com", "agent-browser open https://example.com", "vercel logs", "kubectl get deployments", @@ -105,6 +110,12 @@ describe("protected deployment guidance", () => { expect(skill).toContain("VERCEL_OIDC_TOKEN"); expect(skill).toContain("x-vercel-trusted-oidc-idp-token"); expect(skill).toContain("agent-browser"); + expect(skill).toContain( + "Browser automation: attach the development OIDC token as a header", + ); + expect(skill).toContain( + "short-lived local token as a request header", + ); expect(skill).toContain("same project's Preview deployments by default"); expect(skill).toContain( "does not automatically access protected Production deployments",