Skip to content

Add Ghost-issued revocable agent credentials, Settings UI, and Claude MCP plugin - #372

Merged
mohabbis merged 1 commit into
masterfrom
codex/create-custom-plugins-for-claude-code
Jul 28, 2026
Merged

Add Ghost-issued revocable agent credentials, Settings UI, and Claude MCP plugin#372
mohabbis merged 1 commit into
masterfrom
codex/create-custom-plugins-for-claude-code

Conversation

@mohabbis

Copy link
Copy Markdown
Owner

Motivation

  • Replace the brittle env-bound agent API key with per-user, revocable, hashed bearer credentials that are created in the web UI and usable by MCP/agent clients.
  • Expose a simple UX and API for creating, listing, and revoking these credentials so external agent clients (e.g. Claude Code) can authenticate securely.
  • Provide a bundled Claude Code plugin and a generic MCP bridge that use the new GHOST_ACCESS_TOKEN environment variable.

Description

  • Add a new AgentCredential Prisma model and migration to persist revocable credentials with tokenHash, tokenHint, expiresAt, lastUsedAt, and revokedAt fields, and wire relations to User and Organization.
  • Implement credential helpers in @ghost/core (createAgentToken and hashAgentToken) and export them from the package.
  • Replace the legacy env-based agent auth with DB-backed credential validation in resolveAgentPrincipal, including membership check and lastUsedAt update.
  • Add server routes for credentials: GET /api/settings/agent-credentials, POST /api/settings/agent-credentials, and DELETE /api/settings/agent-credentials/[id] that enforce session auth and handle creation/listing/revocation.
  • Add a client-side Settings component (AgentCredentials) to create, list, and revoke credentials and inject it into the Settings page UI.
  • Update MCP bridge (cloud/apps/mcp), web docs, and tooling to use the new GHOST_ACCESS_TOKEN env var instead of GHOST_AGENT_API_KEY/org/user envs, and add a bundled Claude Code plugin with a stdio MCP shim (plugins/claude-code/ghost).
  • Update cloud/turbo.json to include GHOST_ACCESS_TOKEN in globalEnv and add package exports for ./agent-credentials.
  • Add a unit test packages/core/src/agent/credentials.test.ts to validate token generation and hashing behavior.

Testing

  • Ran the new unit test in @ghost/core via the repo test runner, pnpm -w test, which includes packages/core/src/agent/credentials.test.ts, and the test passed.
  • Existing typecheck/build/test hooks were exercised locally (pnpm -w build / pnpm -w typecheck) during development and reported no errors.

Codex Task

@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ghost Building Building Preview Jul 28, 2026 8:05pm

@mohabbis
mohabbis marked this pull request as ready for review July 28, 2026 20:05

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d4bd8b2fdc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +44 to +45
const generated = createAgentToken();
const credential = await prisma.agentCredential.create({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Record credential lifecycle in the audit log

When a user creates or revokes an agent credential, these routes only mutate AgentCredential and never append an AuditEvent; consequently, credential issuance and revocation are absent from the hash-chained organizational audit trail, making security investigations unable to verify these sensitive lifecycle actions. Record both POST and DELETE operations in the audit chain, ideally atomically with their credential mutations.

AGENTS.md reference: AGENTS.md:L101-L105

Useful? React with 👍 / 👎.

Comment on lines +62 to +65
await prisma.agentCredential.update({
where: { id: credential.id },
data: { lastUsedAt: new Date() },
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Throttle credential last-used writes

When a credential-backed agent polls get_run or makes concurrent read-only calls, every request performs this unconditional database update. That turns each credential into a hot row and generates write/WAL traffic for otherwise read-only requests, so normal polling or a noisy client can serialize calls and place disproportionate load on Postgres. Update lastUsedAt only when it is older than a reasonable interval, or record usage asynchronously.

Useful? React with 👍 / 👎.

Comment on lines +85 to +87
<Button disabled={!name.trim()} onClick={createCredential}>
Create credential
</Button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Disable credential creation while the request is pending

On a slow connection, double-clicking this still-enabled button sends concurrent POST requests and creates multiple valid credentials. Because each completion overwrites the single token state, only one plaintext remains visible while the other active credential's secret is irretrievably lost, forcing the user to identify and revoke the orphan. Track the pending request and disable the create control until it completes.

Useful? React with 👍 / 👎.

Comment on lines +1 to +3
---
description: Use Ghost to find, preview, start, and monitor governed business workflows. Use when the user asks Claude to perform an operation through Ghost or inspect a Ghost run.
---

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the required name to the Claude skill

Claude Agent Skills require both name and description in SKILL.md frontmatter, but this skill declares only the description. The skill loader can therefore reject or omit run-workflow, leaving the README's advertised /ghost:run-workflow command unavailable even if the plugin's MCP server connects successfully. Add a valid name: run-workflow field.

Useful? React with 👍 / 👎.

@mohabbis
mohabbis merged commit a3174a8 into master Jul 28, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant