Skip to content
Conduit

mcp server

paladin

Multi-tenant control plane for S3-compatible object storage: tenant-scoped credentials, Cedar policies, quotas, audit and events. Not an S3 proxy — clients move bytes over presigned URLs. Connect API,

oleg-tkachuk/paladincommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 26, 2026

paladin

ci release sdk

license: backend & console license: proto license: Go SDK license: Python SDK

Go PostgreSQL Connect RPC Cedar MCP Next.js

A multi-tenant control plane for S3-compatible object storage. Applications authenticate with a Paladin credential scoped to a tenant instead of holding storage credentials; Paladin checks each request against the tenant's Cedar policies, resolves the backend and bucket the tenant is on, meters usage against quotas, and writes an audit trail.

Paladin does not proxy traffic to S3. Object bytes move between the client and the storage backend over presigned URLs that Paladin signs; the API carries metadata only. Paladin itself calls S3 to manage buckets and objects — create and delete buckets, open and close multipart uploads, verify a completed upload, copy and delete objects server-side — never to relay a client's upload or download. ARCHITECTURE.md lists every call.

flowchart LR
    op(["Operator · console"])
    agent(["AI agent · MCP"])
    app(["Application · SDK"])

    cp["<b>Paladin</b><br/>IAM · Cedar policy · quotas<br/>object metadata · audit · events"]

    pg[("<b>PostgreSQL</b>")]
    sinks{{"<b>Event sinks</b><br/>webhooks · brokers"}}
    s3[("<b>S3 backends</b><br/>SeaweedFS · MinIO<br/>Garage · AWS")]

    op -- "Connect RPC" --> cp
    agent -- "MCP" --> cp
    app -- "Connect RPC" --> cp
    cp --> pg
    cp -- "events" --> sinks
    cp -- "bucket and object management" --> s3
    app -. "object bytes, presigned" .-> s3

    classDef client fill:#E0F2FE,stroke:#0284C7,color:#0C4A6E
    classDef ui fill:#EDE9FE,stroke:#7C3AED,color:#3B0764
    classDef role fill:#DCFCE7,stroke:#16A34A,color:#14532D
    classDef optional fill:#F1F5F9,stroke:#64748B,color:#334155,stroke-dasharray:5 4
    classDef store fill:#FEF3C7,stroke:#D97706,color:#78350F
    classDef external fill:#FCE7F3,stroke:#DB2777,color:#831843
    class app,agent,op client
    class cp role
    class pg,s3 store
    class sinks external

Access is granted through users, API tokens and capability tokens — short-lived, budgeted and individually revocable. The capability primitive is limes, a Go library of its own with no database driver and no storage SDK among its dependencies; Paladin backs its contracts with PostgreSQL. Besides the Connect API, the console and the Go and Python SDKs, the same operations are exposed over the Model Context Protocol, so AI agents can use them as tools.

Paladin is one Go binary. Each role below runs as its own Deployment (paladin serve <role>), next to a web console:

RoleWhat it does
apithe data plane (object metadata, presigned upload and download URLs) and IAM (sign-in, users, API tokens)
admintenants, buckets, storage backends, quotas, policies, capabilities, audit
mcpthe api and admin operations, as tools for AI agents
workerbackground jobs: bucket provisioning, batch operations, trash purge, lifecycle, migration between backends
dispatcherdelivers events, as CloudEvents 1.0, to webhooks and message brokers (event-delivery-dedup.md)
ingestturns storage-side notifications into object updates; off by default
consolethe web UI, with a BFF in front of api and admin; its own chart and Deployment

It needs PostgreSQL and an S3-compatible store — SeaweedFS, MinIO, Garage or AWS S3.

Contents

Deploy to Kubernetes

Two Helm charts, published to GHCR with every release (vX.Y.Z):

ChartRuns
oci://ghcr.io/oleg-tkachuk/charts/paladin-corethe backend planes, plus the migrate and bootstrap Jobs
oci://ghcr.io/oleg-tkachuk/charts/paladin-consolethe web console and its BFF

The charts and the images they deploy are signed keyless with Sigstore, and each image carries a signed SPDX SBOM per platform; releasing.md shows how to verify them.

The charts run neither PostgreSQL nor the object store: bring PostgreSQL 16+ and an S3-compatible store whose access key may create buckets. Kubernetes 1.25+ and Helm 3.8+.

  1. Create the three database roles, once, as a superuser — the SQL is in docs/install.md.

  2. Put the credentials into Secrets:

    kubectl create namespace paladin
    kubectl -n paladin create secret generic paladin-postgres-app --from-literal=password='<app-password>'
    kubectl -n paladin create secret generic paladin-postgres-migrate --from-literal=password='<migrate-password>'
    kubectl -n paladin create secret generic paladin-s3 \
      --from-literal=access_key='<access-key>' --from-literal=secret_key='<secret-key>'
    
  3. Give the backend chart what it cannot default:

    # paladin-core.yaml
    postgres:
      host: postgres.databases.svc.cluster.local
      sslmode: require
      app:
        existingSecret: paladin-postgres-app
      migrate:
        existingSecret: paladin-postgres-migrate
    config:
      storage:
        backends:
          primary:
            endpoint: http://seaweedfs.storage.svc.cluster.local:8333
            public_endpoint: https://s3.example.com   # what clients reach the store by
            region: us-east-1
    storage:
      s3CredentialsSecret:
        create: false
        existingSecret: paladin-s3
    
  4. Install both charts:

    helm install paladin-core oci://ghcr.io/oleg-tkachuk/charts/paladin-core \
      --version <version> -n paladin -f paladin-core.yaml
    helm install paladin-console oci://ghcr.io/oleg-tkachuk/charts/paladin-console \
      --version <version> -n paladin
    
  5. Sign in as admin, with the password generated on first install:

    kubectl -n paladin get secret paladin-bootstrap-admin -o jsonpath='{.data.password}' | base64 -d
    kubectl -n paladin port-forward svc/paladin-console 3000:3000
    

docs/install.md covers the rest: ingress, TLS between the planes, and what to set when ArgoCD renders the charts.

Documentation

DocumentCovers
ARCHITECTURE.mdwhat the pieces are and why the boundaries fall where they do
backend/README.mdroles, ports, packages, wire contracts, database
frontend/README.mdthe console and its BFF
limesthe capability primitive: tokens, delegation, Biscuit, DPoP, metering
docs/install.mdinstalling on Kubernetes with the Helm charts
docs/task.mdrunning it with Task — compose, a local cluster, the gates — and the prerequisites of each
docs/configuration.mdevery configuration surface, and the validation run at load
docs/upgrading.mdbreaking changes between releases
docs/how-changes-land.mdtrunk, CI, and what a green push to main releases
docs/releasing.mdwhat each tag family publishes and who cuts it
docs/subsystems, ADRs and runbooks
CONTRIBUTING.mdpull requests are not accepted yet; security fixes are
docs/development.mdconventions, test tiers, how a pull request is expected to look
SECURITY.mdreporting a vulnerability
docs/security-model.mdscope, known non-findings, the security model
BACKLOG.mddeferred work, each item with its reason — read before calling a gap an oversight

Layout

PathHolds
backend/the Go control plane: binary, migrations, policies, chart, compose stack
frontend/the Next.js console and BFF, its chart and Playwright suite
proto/the API contract
sdk/go/the Go SDK
sdk/python/the Python SDK
deploy/Grafana dashboards and alerts
scripts/the repository's own contract checks, run by verify-all, and the release and stack helpers
specs/spec-driven-development artifacts, per feature
docs/the documents above

The components share a repository because a wire-contract change is a change to all of them: the proto in proto/ is the source of truth, and the backend, the console and both SDKs generate their stubs from it.

Compatibility is not kept across releases yet, and only main is supported — docs/upgrading.md lists what each release breaks.

License

AGPL-3.0-only — see LICENSE and NOTICE. The API contract in proto/ and the Go and Python SDKs in sdk/ are Apache-2.0, each under its own LICENSE, so a client can embed them without taking on the AGPL; so is limes.

↑↓ navigate openesc close