feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
generator client {
|
|
|
|
|
provider = "prisma-client-js"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
datasource db {
|
|
|
|
|
provider = "postgresql"
|
|
|
|
|
url = env("DATABASE_URL")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Users ──
|
|
|
|
|
|
|
|
|
|
model User {
|
feat: implement v2 3-tier architecture (mcpctl → mcplocal → mcpd)
- Rename local-proxy to mcplocal with HTTP server, LLM pipeline, mcpd discovery
- Add LLM pre-processing: token estimation, filter cache, metrics, Gemini CLI + DeepSeek providers
- Add mcpd auth (login/logout) and MCP proxy endpoints
- Update CLI: dual URLs (mcplocalUrl/mcpdUrl), auth commands, --direct flag
- Add tiered health monitoring, shell completions, e2e integration tests
- 57 test files, 597 tests passing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 11:42:06 +00:00
|
|
|
id String @id @default(cuid())
|
|
|
|
|
email String @unique
|
|
|
|
|
name String?
|
|
|
|
|
passwordHash String
|
|
|
|
|
role Role @default(USER)
|
feat: granular RBAC with resource/operation bindings, users, groups
- Replace admin role with granular roles: view, create, delete, edit, run
- Two binding types: resource bindings (role+resource+optional name) and
operation bindings (role:run + action like backup, logs, impersonate)
- Name-scoped resource bindings for per-instance access control
- Remove role from project members (all permissions via RBAC)
- Add users, groups, RBAC CRUD endpoints and CLI commands
- describe user/group shows all RBAC access (direct + inherited)
- create rbac supports --subject, --binding, --operation flags
- Backup/restore handles users, groups, RBAC definitions
- mcplocal project-based MCP endpoint discovery
- Full test coverage for all new functionality
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:05:19 +00:00
|
|
|
provider String?
|
|
|
|
|
externalId String?
|
feat: implement v2 3-tier architecture (mcpctl → mcplocal → mcpd)
- Rename local-proxy to mcplocal with HTTP server, LLM pipeline, mcpd discovery
- Add LLM pre-processing: token estimation, filter cache, metrics, Gemini CLI + DeepSeek providers
- Add mcpd auth (login/logout) and MCP proxy endpoints
- Update CLI: dual URLs (mcplocalUrl/mcpdUrl), auth commands, --direct flag
- Add tiered health monitoring, shell completions, e2e integration tests
- 57 test files, 597 tests passing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 11:42:06 +00:00
|
|
|
version Int @default(1)
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
|
feat: granular RBAC with resource/operation bindings, users, groups
- Replace admin role with granular roles: view, create, delete, edit, run
- Two binding types: resource bindings (role+resource+optional name) and
operation bindings (role:run + action like backup, logs, impersonate)
- Name-scoped resource bindings for per-instance access control
- Remove role from project members (all permissions via RBAC)
- Add users, groups, RBAC CRUD endpoints and CLI commands
- describe user/group shows all RBAC access (direct + inherited)
- create rbac supports --subject, --binding, --operation flags
- Backup/restore handles users, groups, RBAC definitions
- mcplocal project-based MCP endpoint discovery
- Full test coverage for all new functionality
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:05:19 +00:00
|
|
|
sessions Session[]
|
|
|
|
|
auditLogs AuditLog[]
|
|
|
|
|
ownedProjects Project[]
|
|
|
|
|
groupMemberships GroupMember[]
|
feat(mcpd): McpToken schema + CRUD routes + introspection
Adds a new McpToken Prisma model (project-scoped, SHA-256 hashed at rest,
optional expiry, revocable) plus backing repository, service, and REST
routes. Tokens are a first-class RBAC subject: new 'McpToken' kind is
added to the subject enum and the service auto-creates an RbacDefinition
with subject McpToken:<sha> when bindings are provided.
Creator-permission ceiling: the service rejects any requested binding
the creator cannot already satisfy themselves (re-uses
rbacService.canAccess / canRunOperation). rbacMode=clone snapshots the
creator's full permissions into the token.
Routes:
POST /api/v1/mcptokens create (returns raw token once)
GET /api/v1/mcptokens list (filter by project)
GET /api/v1/mcptokens/:id describe (no secret in response)
POST /api/v1/mcptokens/:id/revoke soft-delete + remove RbacDef
DELETE /api/v1/mcptokens/:id hard-delete
GET /api/v1/mcptokens/introspect validate raw bearer (used by mcplocal)
Extends AuditEvent with optional tokenName/tokenSha fields (indexed) so
token-driven activity can be filtered later. Adds token helpers in
@mcpctl/shared: TOKEN_PREFIX='mcpctl_pat_', generateToken, hashToken,
isMcpToken, timingSafeEqualHex.
Follow-up PRs add the auth-hook dispatch on the prefix, the CLI verbs,
and the HTTP-mode mcplocal that calls /introspect.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 01:00:04 +01:00
|
|
|
mcpTokens McpToken[]
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
|
|
|
|
|
@@index([email])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum Role {
|
|
|
|
|
USER
|
|
|
|
|
ADMIN
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Sessions ──
|
|
|
|
|
|
|
|
|
|
model Session {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
token String @unique
|
|
|
|
|
userId String
|
|
|
|
|
expiresAt DateTime
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([token])
|
|
|
|
|
@@index([userId])
|
|
|
|
|
@@index([expiresAt])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── MCP Servers ──
|
|
|
|
|
|
|
|
|
|
model McpServer {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String @default("")
|
|
|
|
|
packageName String?
|
2026-03-03 19:07:39 +00:00
|
|
|
runtime String?
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
dockerImage String?
|
|
|
|
|
transport Transport @default(STDIO)
|
|
|
|
|
repositoryUrl String?
|
2026-02-22 12:21:25 +00:00
|
|
|
externalUrl String?
|
|
|
|
|
command Json?
|
|
|
|
|
containerPort Int?
|
2026-02-22 13:30:46 +00:00
|
|
|
replicas Int @default(1)
|
feat: replace profiles with kubernetes-style secrets
Replace the confused Profile abstraction with a dedicated Secret resource
following Kubernetes conventions. Servers now have env entries with inline
values or secretRef references. Env vars are resolved and passed to
containers at startup (fixes existing gap).
- Add Secret CRUD (model, repo, service, routes, CLI commands)
- Server env: {name, value} or {name, valueFrom: {secretRef: {name, key}}}
- Add env-resolver utility shared by instance startup and config generation
- Remove all profile-related code (models, services, routes, CLI, tests)
- Update backup/restore for secrets instead of profiles
- describe secret masks values by default, --show-values to reveal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:40:58 +00:00
|
|
|
env Json @default("[]")
|
feat: add MCP healthcheck probes and new templates (grafana, home-assistant, node-red)
- Add healthCheck spec to templates and servers (tool, arguments, interval, timeout, failureThreshold)
- Add healthStatus, lastHealthCheck, events fields to instances
- Create grafana, home-assistant, node-red templates with healthcheck probes
- Add healthcheck probes to existing templates (github, slack, postgres, jira)
- Show HEALTH column in `get instances` and Events section in `describe instance`
- Display healthCheck details in `describe server` and `describe template`
- Schema + storage + display only; actual probe runner is future work
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 22:48:59 +00:00
|
|
|
healthCheck Json?
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
version Int @default(1)
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
|
2026-02-22 22:24:35 +00:00
|
|
|
templateName String?
|
|
|
|
|
templateVersion String?
|
|
|
|
|
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
instances McpInstance[]
|
feat: granular RBAC with resource/operation bindings, users, groups
- Replace admin role with granular roles: view, create, delete, edit, run
- Two binding types: resource bindings (role+resource+optional name) and
operation bindings (role:run + action like backup, logs, impersonate)
- Name-scoped resource bindings for per-instance access control
- Remove role from project members (all permissions via RBAC)
- Add users, groups, RBAC CRUD endpoints and CLI commands
- describe user/group shows all RBAC access (direct + inherited)
- create rbac supports --subject, --binding, --operation flags
- Backup/restore handles users, groups, RBAC definitions
- mcplocal project-based MCP endpoint discovery
- Full test coverage for all new functionality
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:05:19 +00:00
|
|
|
projects ProjectServer[]
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
|
|
|
|
|
@@index([name])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum Transport {
|
|
|
|
|
STDIO
|
|
|
|
|
SSE
|
|
|
|
|
STREAMABLE_HTTP
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-22 22:24:35 +00:00
|
|
|
// ── MCP Templates ──
|
|
|
|
|
|
|
|
|
|
model McpTemplate {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
version String @default("1.0.0")
|
|
|
|
|
description String @default("")
|
|
|
|
|
packageName String?
|
2026-03-03 19:07:39 +00:00
|
|
|
runtime String?
|
2026-02-22 22:24:35 +00:00
|
|
|
dockerImage String?
|
|
|
|
|
transport Transport @default(STDIO)
|
|
|
|
|
repositoryUrl String?
|
|
|
|
|
externalUrl String?
|
|
|
|
|
command Json?
|
|
|
|
|
containerPort Int?
|
|
|
|
|
replicas Int @default(1)
|
|
|
|
|
env Json @default("[]")
|
feat: add MCP healthcheck probes and new templates (grafana, home-assistant, node-red)
- Add healthCheck spec to templates and servers (tool, arguments, interval, timeout, failureThreshold)
- Add healthStatus, lastHealthCheck, events fields to instances
- Create grafana, home-assistant, node-red templates with healthcheck probes
- Add healthcheck probes to existing templates (github, slack, postgres, jira)
- Show HEALTH column in `get instances` and Events section in `describe instance`
- Display healthCheck details in `describe server` and `describe template`
- Schema + storage + display only; actual probe runner is future work
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 22:48:59 +00:00
|
|
|
healthCheck Json?
|
2026-02-22 22:24:35 +00:00
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
@@index([name])
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-18 19:29:55 +01:00
|
|
|
// ── Secret Backends ──
|
|
|
|
|
//
|
|
|
|
|
// Pluggable storage for Secret.data. Default is `plaintext` (data stored in
|
|
|
|
|
// Secret.data JSON). Other drivers (e.g. `openbao`) store only a reference in
|
|
|
|
|
// Secret.externalRef and fetch actual values from the external system at read
|
|
|
|
|
// time. A `plaintext` row is seeded on first startup so the system always has
|
|
|
|
|
// a viable backend; additional backends are user-managed via
|
|
|
|
|
// `mcpctl create secretbackend`.
|
|
|
|
|
|
|
|
|
|
model SecretBackend {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
type String // plaintext | openbao | (future: vault, aws-sm, ...)
|
|
|
|
|
config Json @default("{}") // type-specific: url, mount, namespace, tokenSecretRef
|
feat(openbao): wizard-provisioning + daily token rotation
One-command setup replaces the 6-step manual flow — `mcpctl create
secretbackend bao --type openbao --wizard` takes the OpenBao admin token
once, provisions a narrow policy + token role, mints the first periodic
token, stores it on mcpd, verifies end-to-end, and prints the migration
command. The admin token is NEVER persisted.
The stored credential auto-rotates daily: mcpd mints a successor via the
token role (self-rotation capability is part of the policy it was issued
with), verifies the successor, writes it over the backing Secret, then
revokes the predecessor by accessor. TTL 720h means a week of rotation
failures still leaves 20+ days of runway.
Shared:
- New `@mcpctl/shared/vault` — pure HTTP wrappers (verifyHealth,
ensureKvV2, writePolicy, ensureTokenRole, mintRoleToken, revokeAccessor,
lookupSelf, testWriteReadDelete) and policy HCL builder.
mcpd:
- `tokenMeta Json @default("{}")` on SecretBackend. Self-healing schema
migration — empty default lets `prisma db push` add the column cleanly.
- SecretBackendRotator.rotateOne: mint → verify → persist → revoke-old →
update tokenMeta. Failures surface via `lastRotationError` on the row;
the old token keeps working.
- SecretBackendRotatorLoop: on startup rotates overdue backends, schedules
per-backend timers with ±10min jitter. Stops cleanly on shutdown.
- New `POST /api/v1/secretbackends/:id/rotate` (operation
`rotate-secretbackend` — added to bootstrap-admin's auto-migrated ops
alongside migrate-secrets, which was previously missing too).
CLI:
- `--wizard` on `create secretbackend` delegates to the interactive flow.
All prompts can be pre-answered via flags (--url, --admin-token,
--mount, --path-prefix, --policy-name, --token-role,
--no-promote-default) for CI.
- `mcpctl rotate secretbackend <name>` — convenience verb; hits the new
rotate endpoint.
- `describe secretbackend` renders a Token health section (healthy /
STALE / WARNING / ERROR) with generated/renewal/expiry timestamps and
last rotation error. Only shown when tokenMeta.rotatable is true — the
existing k8s-auth + static-token backends don't surface it.
Tests: 15 vault-client unit tests (shared), 8 rotator unit tests (mcpd),
3 wizard flow tests (cli, including a regression test that the admin
token never appears in stdout). Full suite 1885/1885 (+32). Completions
regenerated for the new flags.
Out of scope (explicit): kubernetes-auth wizard, Vault Enterprise
namespaces in the wizard path, rotation for non-wizard static-token
backends. See plan file for details.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 17:20:37 +01:00
|
|
|
// Runtime metadata for auto-rotating backend credentials (openbao token
|
|
|
|
|
// auth). Fields: generatedAt, nextRenewalAt, validUntil, lastRotationAt,
|
|
|
|
|
// lastRotationError, rotatable (true only for wizard-provisioned tokens).
|
|
|
|
|
// Empty object for backends that don't use rotation (plaintext, kubernetes
|
|
|
|
|
// auth, or static tokens). Managed entirely by the rotator service.
|
|
|
|
|
tokenMeta Json @default("{}")
|
2026-04-18 19:29:55 +01:00
|
|
|
isDefault Boolean @default(false) // exactly one row has isDefault=true
|
|
|
|
|
description String @default("")
|
|
|
|
|
version Int @default(1)
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
secrets Secret[]
|
|
|
|
|
|
|
|
|
|
@@index([name])
|
|
|
|
|
@@index([isDefault])
|
|
|
|
|
}
|
|
|
|
|
|
feat: replace profiles with kubernetes-style secrets
Replace the confused Profile abstraction with a dedicated Secret resource
following Kubernetes conventions. Servers now have env entries with inline
values or secretRef references. Env vars are resolved and passed to
containers at startup (fixes existing gap).
- Add Secret CRUD (model, repo, service, routes, CLI commands)
- Server env: {name, value} or {name, valueFrom: {secretRef: {name, key}}}
- Add env-resolver utility shared by instance startup and config generation
- Remove all profile-related code (models, services, routes, CLI, tests)
- Update backup/restore for secrets instead of profiles
- describe secret masks values by default, --show-values to reveal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:40:58 +00:00
|
|
|
// ── Secrets ──
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
|
feat: replace profiles with kubernetes-style secrets
Replace the confused Profile abstraction with a dedicated Secret resource
following Kubernetes conventions. Servers now have env entries with inline
values or secretRef references. Env vars are resolved and passed to
containers at startup (fixes existing gap).
- Add Secret CRUD (model, repo, service, routes, CLI commands)
- Server env: {name, value} or {name, valueFrom: {secretRef: {name, key}}}
- Add env-resolver utility shared by instance startup and config generation
- Remove all profile-related code (models, services, routes, CLI, tests)
- Update backup/restore for secrets instead of profiles
- describe secret masks values by default, --show-values to reveal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:40:58 +00:00
|
|
|
model Secret {
|
2026-04-18 19:29:55 +01:00
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
2026-04-19 22:45:08 +01:00
|
|
|
// FK to SecretBackend. Default empty string lets `prisma db push` add the
|
|
|
|
|
// column to pre-existing rows without a data-loss reset; `bootstrapSecretBackends`
|
|
|
|
|
// then points any empty-string values at the seeded `default` plaintext backend
|
|
|
|
|
// on next mcpd startup. New rows written by SecretService always carry a
|
|
|
|
|
// valid FK immediately.
|
|
|
|
|
backendId String @default("")
|
2026-04-18 19:29:55 +01:00
|
|
|
data Json @default("{}") // populated by plaintext backend only
|
|
|
|
|
externalRef String @default("") // populated by non-plaintext backends (e.g. "mount/path#v3")
|
2026-04-24 00:57:06 +01:00
|
|
|
// Sorted list of the secret's data keys WITHOUT their values. Populated on
|
|
|
|
|
// every create/update/migrate so list views and describe-without-reveal can
|
|
|
|
|
// show "this secret has GRAFANA_URL + GRAFANA_TOKEN" without fetching the
|
|
|
|
|
// backing data. For pre-existing rows the field is empty until the next
|
|
|
|
|
// write or a lazy resolve in getById fills it in.
|
|
|
|
|
keyNames Json @default("[]")
|
2026-04-18 19:29:55 +01:00
|
|
|
version Int @default(1)
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
backend SecretBackend @relation(fields: [backendId], references: [id])
|
feat(mcpd): Llm resource — CRUD + CLI + apply
Why: every client that wants an LLM (the agent, HTTP-mode mcplocal, Claude
Code's STDIO mcplocal) today has to know the provider URL + key, and each
user's ~/.mcpctl/config.json carries them. Centralising the catalogue on the
server is the prerequisite for Phase 2 (mcpd proxies inference so credentials
never leave the cluster).
This phase adds the `Llm` resource and its CRUD surface — no proxy yet, no
client pivot yet. Just enough to register what you have.
Schema:
- New `Llm` model: name/type/model/url/tier/description + {apiKeySecretId,
apiKeySecretKey} FK pair. Reverse `llms` relation on Secret.
- Provider types: anthropic | openai | deepseek | vllm | ollama | gemini-cli.
- Tiers: fast | heavy.
mcpd:
- LlmRepository + LlmService + Zod validation schema + /api/v1/llms routes.
- API surface exposes `apiKeyRef: {name, key}` — the service translates to/
from the FK pair so clients never deal in cuids.
- `resolveApiKey(llmName)` reads through SecretService (which itself dispatches
to the right SecretBackend). That's the hook Phase 2's inference proxy uses.
- RBAC: added `'llms'` to RBAC_RESOURCES + resource alias. Standard
view/create/edit/delete semantics.
- Wired into main.ts (repo, service, routes).
CLI:
- `mcpctl create llm <name> --type X --model Y --tier fast|heavy --api-key-ref SECRET/KEY [--url ...] [--extra k=v ...]`
- `mcpctl get|describe|delete llm` — standard resource verbs.
- `mcpctl apply -f` with `kind: llm` (single- or multi-doc yaml/json).
Applied after secrets, before servers — apiKeyRef resolves an existing Secret.
- Shell completions regenerated.
Tests: 11 service unit tests + 9 route tests (happy path, 404s, 409, validation).
Full suite 1812/1812 (+20 from the 1792 Phase 0 baseline). TypeScript clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 21:28:43 +01:00
|
|
|
llms Llm[]
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
|
feat: replace profiles with kubernetes-style secrets
Replace the confused Profile abstraction with a dedicated Secret resource
following Kubernetes conventions. Servers now have env entries with inline
values or secretRef references. Env vars are resolved and passed to
containers at startup (fixes existing gap).
- Add Secret CRUD (model, repo, service, routes, CLI commands)
- Server env: {name, value} or {name, valueFrom: {secretRef: {name, key}}}
- Add env-resolver utility shared by instance startup and config generation
- Remove all profile-related code (models, services, routes, CLI, tests)
- Update backup/restore for secrets instead of profiles
- describe secret masks values by default, --show-values to reveal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 18:40:58 +00:00
|
|
|
@@index([name])
|
2026-04-18 19:29:55 +01:00
|
|
|
@@index([backendId])
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
}
|
|
|
|
|
|
feat(mcpd): Llm resource — CRUD + CLI + apply
Why: every client that wants an LLM (the agent, HTTP-mode mcplocal, Claude
Code's STDIO mcplocal) today has to know the provider URL + key, and each
user's ~/.mcpctl/config.json carries them. Centralising the catalogue on the
server is the prerequisite for Phase 2 (mcpd proxies inference so credentials
never leave the cluster).
This phase adds the `Llm` resource and its CRUD surface — no proxy yet, no
client pivot yet. Just enough to register what you have.
Schema:
- New `Llm` model: name/type/model/url/tier/description + {apiKeySecretId,
apiKeySecretKey} FK pair. Reverse `llms` relation on Secret.
- Provider types: anthropic | openai | deepseek | vllm | ollama | gemini-cli.
- Tiers: fast | heavy.
mcpd:
- LlmRepository + LlmService + Zod validation schema + /api/v1/llms routes.
- API surface exposes `apiKeyRef: {name, key}` — the service translates to/
from the FK pair so clients never deal in cuids.
- `resolveApiKey(llmName)` reads through SecretService (which itself dispatches
to the right SecretBackend). That's the hook Phase 2's inference proxy uses.
- RBAC: added `'llms'` to RBAC_RESOURCES + resource alias. Standard
view/create/edit/delete semantics.
- Wired into main.ts (repo, service, routes).
CLI:
- `mcpctl create llm <name> --type X --model Y --tier fast|heavy --api-key-ref SECRET/KEY [--url ...] [--extra k=v ...]`
- `mcpctl get|describe|delete llm` — standard resource verbs.
- `mcpctl apply -f` with `kind: llm` (single- or multi-doc yaml/json).
Applied after secrets, before servers — apiKeyRef resolves an existing Secret.
- Shell completions regenerated.
Tests: 11 service unit tests + 9 route tests (happy path, 404s, 409, validation).
Full suite 1812/1812 (+20 from the 1792 Phase 0 baseline). TypeScript clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 21:28:43 +01:00
|
|
|
// ── LLMs ──
|
|
|
|
|
//
|
|
|
|
|
// Server-managed LLM providers. Clients (agent, HTTP-mode mcplocal) send
|
|
|
|
|
// OpenAI-format requests to `mcpd /api/v1/llms/:name/infer` — mcpd attaches the
|
|
|
|
|
// provider API key server-side so credentials never leave the cluster.
|
|
|
|
|
// Credentials are stored by reference: `apiKeySecret` points at a Secret, and
|
|
|
|
|
// `apiKeySecretKey` names the key within that secret's data.
|
|
|
|
|
|
|
|
|
|
model Llm {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
type String // anthropic | openai | deepseek | vllm | ollama | gemini-cli
|
|
|
|
|
model String // e.g. claude-3-5-sonnet-20241022
|
|
|
|
|
url String @default("") // endpoint (empty for provider default)
|
|
|
|
|
tier String @default("fast") // fast | heavy
|
|
|
|
|
description String @default("")
|
|
|
|
|
apiKeySecretId String? // FK to Secret
|
|
|
|
|
apiKeySecretKey String? // key inside the Secret's data
|
|
|
|
|
extraConfig Json @default("{}") // per-type extras
|
|
|
|
|
version Int @default(1)
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
apiKeySecret Secret? @relation(fields: [apiKeySecretId], references: [id], onDelete: SetNull)
|
|
|
|
|
|
|
|
|
|
@@index([name])
|
|
|
|
|
@@index([tier])
|
|
|
|
|
@@index([apiKeySecretId])
|
|
|
|
|
}
|
|
|
|
|
|
feat: granular RBAC with resource/operation bindings, users, groups
- Replace admin role with granular roles: view, create, delete, edit, run
- Two binding types: resource bindings (role+resource+optional name) and
operation bindings (role:run + action like backup, logs, impersonate)
- Name-scoped resource bindings for per-instance access control
- Remove role from project members (all permissions via RBAC)
- Add users, groups, RBAC CRUD endpoints and CLI commands
- describe user/group shows all RBAC access (direct + inherited)
- create rbac supports --subject, --binding, --operation flags
- Backup/restore handles users, groups, RBAC definitions
- mcplocal project-based MCP endpoint discovery
- Full test coverage for all new functionality
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:05:19 +00:00
|
|
|
// ── Groups ──
|
|
|
|
|
|
|
|
|
|
model Group {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String @default("")
|
|
|
|
|
version Int @default(1)
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
members GroupMember[]
|
|
|
|
|
|
|
|
|
|
@@index([name])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model GroupMember {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
groupId String
|
|
|
|
|
userId String
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
group Group @relation(fields: [groupId], references: [id], onDelete: Cascade)
|
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([groupId, userId])
|
|
|
|
|
@@index([groupId])
|
|
|
|
|
@@index([userId])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── RBAC Definitions ──
|
|
|
|
|
|
|
|
|
|
model RbacDefinition {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
subjects Json @default("[]")
|
|
|
|
|
roleBindings Json @default("[]")
|
|
|
|
|
version Int @default(1)
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
|
|
|
|
|
@@index([name])
|
|
|
|
|
}
|
|
|
|
|
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
// ── Projects ──
|
|
|
|
|
|
|
|
|
|
model Project {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String @unique
|
|
|
|
|
description String @default("")
|
2026-02-24 14:53:00 +00:00
|
|
|
prompt String @default("")
|
2026-03-03 19:07:39 +00:00
|
|
|
proxyModel String @default("")
|
feat: gated project experience & prompt intelligence
Implements the full gated session flow and prompt intelligence system:
- Prisma schema: add gated, priority, summary, chapters, linkTarget fields
- Session gate: state machine (gated → begin_session → ungated) with LLM-powered
tool selection based on prompt index
- Tag matcher: intelligent prompt-to-tool matching with project/server/action tags
- LLM selector: tiered provider selection (fast for gating, heavy for complex tasks)
- Link resolver: cross-project MCP resource references (project/server:uri format)
- Prompt summary service: LLM-generated summaries and chapter extraction
- System project bootstrap: ensures default project exists on startup
- Structural link health checks: enrichWithLinkStatus on prompt GET endpoints
- CLI: create prompt --priority/--link, create project --gated/--no-gated,
describe project shows prompts section, get prompts shows PRI/LINK/STATUS
- Apply/edit: priority, linkTarget, gated fields supported
- Shell completions: fish updated with new flags
- 1,253 tests passing across all packages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:22:42 +00:00
|
|
|
gated Boolean @default(true)
|
2026-03-03 19:07:39 +00:00
|
|
|
llmProvider String?
|
|
|
|
|
llmModel String?
|
|
|
|
|
serverOverrides Json?
|
|
|
|
|
ownerId String
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
version Int @default(1)
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
|
2026-02-24 14:53:00 +00:00
|
|
|
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
|
|
|
|
|
servers ProjectServer[]
|
|
|
|
|
prompts Prompt[]
|
|
|
|
|
promptRequests PromptRequest[]
|
feat(mcpd): McpToken schema + CRUD routes + introspection
Adds a new McpToken Prisma model (project-scoped, SHA-256 hashed at rest,
optional expiry, revocable) plus backing repository, service, and REST
routes. Tokens are a first-class RBAC subject: new 'McpToken' kind is
added to the subject enum and the service auto-creates an RbacDefinition
with subject McpToken:<sha> when bindings are provided.
Creator-permission ceiling: the service rejects any requested binding
the creator cannot already satisfy themselves (re-uses
rbacService.canAccess / canRunOperation). rbacMode=clone snapshots the
creator's full permissions into the token.
Routes:
POST /api/v1/mcptokens create (returns raw token once)
GET /api/v1/mcptokens list (filter by project)
GET /api/v1/mcptokens/:id describe (no secret in response)
POST /api/v1/mcptokens/:id/revoke soft-delete + remove RbacDef
DELETE /api/v1/mcptokens/:id hard-delete
GET /api/v1/mcptokens/introspect validate raw bearer (used by mcplocal)
Extends AuditEvent with optional tokenName/tokenSha fields (indexed) so
token-driven activity can be filtered later. Adds token helpers in
@mcpctl/shared: TOKEN_PREFIX='mcpctl_pat_', generateToken, hashToken,
isMcpToken, timingSafeEqualHex.
Follow-up PRs add the auth-hook dispatch on the prefix, the CLI verbs,
and the HTTP-mode mcplocal that calls /introspect.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 01:00:04 +01:00
|
|
|
mcpTokens McpToken[]
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
|
|
|
|
|
@@index([name])
|
|
|
|
|
@@index([ownerId])
|
|
|
|
|
}
|
|
|
|
|
|
feat: granular RBAC with resource/operation bindings, users, groups
- Replace admin role with granular roles: view, create, delete, edit, run
- Two binding types: resource bindings (role+resource+optional name) and
operation bindings (role:run + action like backup, logs, impersonate)
- Name-scoped resource bindings for per-instance access control
- Remove role from project members (all permissions via RBAC)
- Add users, groups, RBAC CRUD endpoints and CLI commands
- describe user/group shows all RBAC access (direct + inherited)
- create rbac supports --subject, --binding, --operation flags
- Backup/restore handles users, groups, RBAC definitions
- mcplocal project-based MCP endpoint discovery
- Full test coverage for all new functionality
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:05:19 +00:00
|
|
|
model ProjectServer {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
projectId String
|
|
|
|
|
serverId String
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
|
|
|
server McpServer @relation(fields: [serverId], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([projectId, serverId])
|
|
|
|
|
}
|
|
|
|
|
|
feat(mcpd): McpToken schema + CRUD routes + introspection
Adds a new McpToken Prisma model (project-scoped, SHA-256 hashed at rest,
optional expiry, revocable) plus backing repository, service, and REST
routes. Tokens are a first-class RBAC subject: new 'McpToken' kind is
added to the subject enum and the service auto-creates an RbacDefinition
with subject McpToken:<sha> when bindings are provided.
Creator-permission ceiling: the service rejects any requested binding
the creator cannot already satisfy themselves (re-uses
rbacService.canAccess / canRunOperation). rbacMode=clone snapshots the
creator's full permissions into the token.
Routes:
POST /api/v1/mcptokens create (returns raw token once)
GET /api/v1/mcptokens list (filter by project)
GET /api/v1/mcptokens/:id describe (no secret in response)
POST /api/v1/mcptokens/:id/revoke soft-delete + remove RbacDef
DELETE /api/v1/mcptokens/:id hard-delete
GET /api/v1/mcptokens/introspect validate raw bearer (used by mcplocal)
Extends AuditEvent with optional tokenName/tokenSha fields (indexed) so
token-driven activity can be filtered later. Adds token helpers in
@mcpctl/shared: TOKEN_PREFIX='mcpctl_pat_', generateToken, hashToken,
isMcpToken, timingSafeEqualHex.
Follow-up PRs add the auth-hook dispatch on the prefix, the CLI verbs,
and the HTTP-mode mcplocal that calls /introspect.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 01:00:04 +01:00
|
|
|
// ── MCP Tokens (bearer credentials for HTTP-mode mcplocal) ──
|
|
|
|
|
//
|
|
|
|
|
// Raw value format: `mcpctl_pat_<32 base62 chars>`. The raw value is shown
|
|
|
|
|
// exactly once at create time; only the SHA-256 hash is persisted. Tokens are
|
|
|
|
|
// scoped to exactly one project — they're only valid at
|
|
|
|
|
// `/projects/<that-project>/mcp`. Creator's RBAC is the ceiling; the service
|
|
|
|
|
// rejects bindings that exceed what the creator themselves can do.
|
|
|
|
|
|
|
|
|
|
model McpToken {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String
|
|
|
|
|
projectId String
|
|
|
|
|
tokenHash String @unique
|
|
|
|
|
tokenPrefix String
|
|
|
|
|
ownerId String
|
|
|
|
|
description String @default("")
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
expiresAt DateTime?
|
|
|
|
|
lastUsedAt DateTime?
|
|
|
|
|
revokedAt DateTime?
|
|
|
|
|
|
|
|
|
|
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
|
|
|
owner User @relation(fields: [ownerId], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([name, projectId])
|
|
|
|
|
@@index([tokenHash])
|
|
|
|
|
@@index([projectId])
|
|
|
|
|
@@index([ownerId])
|
|
|
|
|
}
|
|
|
|
|
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
// ── MCP Instances (running containers) ──
|
|
|
|
|
|
|
|
|
|
model McpInstance {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
serverId String
|
|
|
|
|
containerId String?
|
|
|
|
|
status InstanceStatus @default(STOPPED)
|
|
|
|
|
port Int?
|
feat: add MCP healthcheck probes and new templates (grafana, home-assistant, node-red)
- Add healthCheck spec to templates and servers (tool, arguments, interval, timeout, failureThreshold)
- Add healthStatus, lastHealthCheck, events fields to instances
- Create grafana, home-assistant, node-red templates with healthcheck probes
- Add healthcheck probes to existing templates (github, slack, postgres, jira)
- Show HEALTH column in `get instances` and Events section in `describe instance`
- Display healthCheck details in `describe server` and `describe template`
- Schema + storage + display only; actual probe runner is future work
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 22:48:59 +00:00
|
|
|
metadata Json @default("{}")
|
|
|
|
|
healthStatus String?
|
|
|
|
|
lastHealthCheck DateTime?
|
|
|
|
|
events Json @default("[]")
|
|
|
|
|
version Int @default(1)
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
|
|
|
|
|
server McpServer @relation(fields: [serverId], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([serverId])
|
|
|
|
|
@@index([status])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum InstanceStatus {
|
|
|
|
|
STARTING
|
|
|
|
|
RUNNING
|
|
|
|
|
STOPPING
|
|
|
|
|
STOPPED
|
|
|
|
|
ERROR
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-24 14:53:00 +00:00
|
|
|
// ── Prompts (approved content resources) ──
|
|
|
|
|
|
|
|
|
|
model Prompt {
|
feat: gated project experience & prompt intelligence
Implements the full gated session flow and prompt intelligence system:
- Prisma schema: add gated, priority, summary, chapters, linkTarget fields
- Session gate: state machine (gated → begin_session → ungated) with LLM-powered
tool selection based on prompt index
- Tag matcher: intelligent prompt-to-tool matching with project/server/action tags
- LLM selector: tiered provider selection (fast for gating, heavy for complex tasks)
- Link resolver: cross-project MCP resource references (project/server:uri format)
- Prompt summary service: LLM-generated summaries and chapter extraction
- System project bootstrap: ensures default project exists on startup
- Structural link health checks: enrichWithLinkStatus on prompt GET endpoints
- CLI: create prompt --priority/--link, create project --gated/--no-gated,
describe project shows prompts section, get prompts shows PRI/LINK/STATUS
- Apply/edit: priority, linkTarget, gated fields supported
- Shell completions: fish updated with new flags
- 1,253 tests passing across all packages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:22:42 +00:00
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String
|
|
|
|
|
content String @db.Text
|
|
|
|
|
projectId String?
|
|
|
|
|
priority Int @default(5)
|
|
|
|
|
summary String? @db.Text
|
|
|
|
|
chapters Json?
|
|
|
|
|
linkTarget String?
|
|
|
|
|
version Int @default(1)
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
2026-02-24 14:53:00 +00:00
|
|
|
|
|
|
|
|
project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([name, projectId])
|
|
|
|
|
@@index([projectId])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── Prompt Requests (pending proposals from LLM sessions) ──
|
|
|
|
|
|
|
|
|
|
model PromptRequest {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String
|
|
|
|
|
content String @db.Text
|
|
|
|
|
projectId String?
|
feat: gated project experience & prompt intelligence
Implements the full gated session flow and prompt intelligence system:
- Prisma schema: add gated, priority, summary, chapters, linkTarget fields
- Session gate: state machine (gated → begin_session → ungated) with LLM-powered
tool selection based on prompt index
- Tag matcher: intelligent prompt-to-tool matching with project/server/action tags
- LLM selector: tiered provider selection (fast for gating, heavy for complex tasks)
- Link resolver: cross-project MCP resource references (project/server:uri format)
- Prompt summary service: LLM-generated summaries and chapter extraction
- System project bootstrap: ensures default project exists on startup
- Structural link health checks: enrichWithLinkStatus on prompt GET endpoints
- CLI: create prompt --priority/--link, create project --gated/--no-gated,
describe project shows prompts section, get prompts shows PRI/LINK/STATUS
- Apply/edit: priority, linkTarget, gated fields supported
- Shell completions: fish updated with new flags
- 1,253 tests passing across all packages
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:22:42 +00:00
|
|
|
priority Int @default(5)
|
2026-02-24 14:53:00 +00:00
|
|
|
createdBySession String?
|
|
|
|
|
createdByUserId String?
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
project Project? @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@unique([name, projectId])
|
|
|
|
|
@@index([projectId])
|
|
|
|
|
@@index([createdBySession])
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-03 19:07:39 +00:00
|
|
|
// ── Audit Events (pipeline/gate/tool trace from mcplocal) ──
|
|
|
|
|
|
|
|
|
|
model AuditEvent {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
timestamp DateTime
|
|
|
|
|
sessionId String
|
|
|
|
|
projectName String
|
|
|
|
|
eventKind String
|
|
|
|
|
source String
|
|
|
|
|
verified Boolean @default(false)
|
|
|
|
|
serverName String?
|
|
|
|
|
correlationId String?
|
|
|
|
|
parentEventId String?
|
2026-03-07 00:18:58 +00:00
|
|
|
userName String?
|
feat(mcpd): McpToken schema + CRUD routes + introspection
Adds a new McpToken Prisma model (project-scoped, SHA-256 hashed at rest,
optional expiry, revocable) plus backing repository, service, and REST
routes. Tokens are a first-class RBAC subject: new 'McpToken' kind is
added to the subject enum and the service auto-creates an RbacDefinition
with subject McpToken:<sha> when bindings are provided.
Creator-permission ceiling: the service rejects any requested binding
the creator cannot already satisfy themselves (re-uses
rbacService.canAccess / canRunOperation). rbacMode=clone snapshots the
creator's full permissions into the token.
Routes:
POST /api/v1/mcptokens create (returns raw token once)
GET /api/v1/mcptokens list (filter by project)
GET /api/v1/mcptokens/:id describe (no secret in response)
POST /api/v1/mcptokens/:id/revoke soft-delete + remove RbacDef
DELETE /api/v1/mcptokens/:id hard-delete
GET /api/v1/mcptokens/introspect validate raw bearer (used by mcplocal)
Extends AuditEvent with optional tokenName/tokenSha fields (indexed) so
token-driven activity can be filtered later. Adds token helpers in
@mcpctl/shared: TOKEN_PREFIX='mcpctl_pat_', generateToken, hashToken,
isMcpToken, timingSafeEqualHex.
Follow-up PRs add the auth-hook dispatch on the prefix, the CLI verbs,
and the HTTP-mode mcplocal that calls /introspect.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 01:00:04 +01:00
|
|
|
tokenName String?
|
|
|
|
|
tokenSha String?
|
2026-03-03 19:07:39 +00:00
|
|
|
payload Json
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
@@index([sessionId])
|
|
|
|
|
@@index([projectName])
|
|
|
|
|
@@index([correlationId])
|
|
|
|
|
@@index([timestamp])
|
|
|
|
|
@@index([eventKind])
|
2026-03-07 00:18:58 +00:00
|
|
|
@@index([userName])
|
feat(mcpd): McpToken schema + CRUD routes + introspection
Adds a new McpToken Prisma model (project-scoped, SHA-256 hashed at rest,
optional expiry, revocable) plus backing repository, service, and REST
routes. Tokens are a first-class RBAC subject: new 'McpToken' kind is
added to the subject enum and the service auto-creates an RbacDefinition
with subject McpToken:<sha> when bindings are provided.
Creator-permission ceiling: the service rejects any requested binding
the creator cannot already satisfy themselves (re-uses
rbacService.canAccess / canRunOperation). rbacMode=clone snapshots the
creator's full permissions into the token.
Routes:
POST /api/v1/mcptokens create (returns raw token once)
GET /api/v1/mcptokens list (filter by project)
GET /api/v1/mcptokens/:id describe (no secret in response)
POST /api/v1/mcptokens/:id/revoke soft-delete + remove RbacDef
DELETE /api/v1/mcptokens/:id hard-delete
GET /api/v1/mcptokens/introspect validate raw bearer (used by mcplocal)
Extends AuditEvent with optional tokenName/tokenSha fields (indexed) so
token-driven activity can be filtered later. Adds token helpers in
@mcpctl/shared: TOKEN_PREFIX='mcpctl_pat_', generateToken, hashToken,
isMcpToken, timingSafeEqualHex.
Follow-up PRs add the auth-hook dispatch on the prefix, the CLI verbs,
and the HTTP-mode mcplocal that calls /introspect.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 01:00:04 +01:00
|
|
|
@@index([tokenSha])
|
2026-03-03 19:07:39 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-08 01:14:28 +00:00
|
|
|
// ── Backup Pending Queue ──
|
|
|
|
|
|
|
|
|
|
model BackupPending {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
resourceKind String
|
|
|
|
|
resourceName String
|
|
|
|
|
action String // 'create' | 'update' | 'delete'
|
|
|
|
|
userName String
|
|
|
|
|
yamlContent String? @db.Text
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
@@index([createdAt])
|
|
|
|
|
}
|
|
|
|
|
|
feat: implement database schema with Prisma ORM
Add PostgreSQL schema with 8 models (User, Session, McpServer, McpProfile,
Project, ProjectMcpProfile, McpInstance, AuditLog), comprehensive model
tests (31 passing), seed data for default MCP servers, and package exports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 04:10:40 +00:00
|
|
|
// ── Audit Logs ──
|
|
|
|
|
|
|
|
|
|
model AuditLog {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
userId String
|
|
|
|
|
action String
|
|
|
|
|
resource String
|
|
|
|
|
resourceId String?
|
|
|
|
|
details Json @default("{}")
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
|
|
|
|
|
|
|
|
@@index([userId])
|
|
|
|
|
@@index([action])
|
|
|
|
|
@@index([resource])
|
|
|
|
|
@@index([createdAt])
|
|
|
|
|
}
|