System Overview
Core Components
CLI (apps/cli)
The tank command-line tool developers interact with.
Technology: TypeScript, Node.js 24+, Commander.js
Responsibilities:
- Parse and validate
skills.jsonmanifests - Generate and verify
skills.lockwith SHA-512 integrity hashes - Resolve dependency trees using semver
- Communicate with the registry API
- Verify package integrity locally
- Display audit information and permission summaries
- 16 commands (install, publish, audit, verify, etc.)
- OAuth authentication flow (browser → poll → API key)
- Tarball packer with security filters (reject symlinks, path traversal)
- Lockfile generation with deterministic JSON serialization
Registry API (apps/web)
The Next.js 15 application serving as the skill registry.
Technology: Next.js 15 App Router, Drizzle ORM, PostgreSQL
Responsibilities:
- Accept and validate skill publishes
- Run the publish pipeline (analyze, validate, score)
- Serve skill metadata and packages
- Maintain audit history
- Handle search queries with full-text search
- Provide web UI for browsing and management
/api/v1/skills— Publish, search, download/api/v1/cli-auth— OAuth flow for CLI/api/admin— Admin moderation and management
- Dual schema:
schema.ts(domain tables) +auth-schema.ts(better-auth auto-generated) - Drizzle ORM — type-safe queries, no raw SQL
- Full-text search — GIN index on skills table with trigram similarity
Security Scanner (python-api)
The 6-stage Python pipeline for static analysis.
Technology: Python 3.14+, FastAPI, Pydantic 2
Stages:
- Stage 0 (Ingest) — Hash computation, file inventory
- Stage 1 (Structure) — Package structure validation
- Stage 2 (Static) — AST analysis, regex patterns, permission cross-checking
- Stage 3 (Injection) — Prompt injection detection
- Stage 4 (Secrets) — Credential and secret scanning
- Stage 5 (Supply Chain) — Dependency vulnerability checking via OSV API
- 1+ critical findings → FAIL
- 4+ high findings → FAIL
- 1-3 high findings → FLAGGED
- Medium/low findings → PASS_WITH_NOTES
Shared Package (packages/shared)
Shared Zod schemas, TypeScript types, and constants.
Exports:
skillsJsonSchema— Manifest validationskillsLockSchema— Lockfile validationpermissionsSchema— Permission modelREGISTRY_URL— API base URL constant- Semver resolver utilities
- Never add side-effect dependencies
- Never mutate exported constants
Technology Stack
Frontend
- Next.js 15 — App Router with Server Components
- Tailwind CSS v4 — Styling via
@tailwindcss/postcss - shadcn/ui — Base UI components
- better-auth — Authentication (GitHub OAuth + OIDC SSO)
Backend
- PostgreSQL 17 — Primary database
- Drizzle ORM — Type-safe queries
- Supabase Storage — Tarball storage (or on-prem alternative)
- Resend — Email service (optional)
- Redis — Caching layer (optional)
Tooling
- pnpm 10.29.3 — Package manager (enforced via
packageManagerfield) - Turbo — Monorepo orchestration
- Vitest — TypeScript testing
- pytest — Python testing
- react-doctor — React linting (60+ rules)
Permission System
The permission model is Tank’s core security innovation.Three Layers
- Skill declaration — Each skill declares required permissions in its manifest
- Project budget — Each project declares allowed permissions in
skills.json - Install-time enforcement — CLI blocks skills exceeding the project budget
- Scan-time cross-check — Scanner extracts permissions from code and flags mismatches
- Runtime enforcement (planned, Phase 3) — Sandbox blocks undeclared operations
Permission Types
network:outbound— Make HTTP/HTTPS requests (with domain patterns)network:inbound— Listen on portsfilesystem:read— Read files (with glob patterns)filesystem:write— Write files (with glob patterns)subprocess— Spawn child processessecrets— Access environment variables
Publish Pipeline
Every skill goes through a multi-stage validation pipeline before entering the registry:Audit Score (0-10)
Always 8 weighted checks:- SKILL.md present (1 pt) — Manifest name non-empty
- Description present (1 pt) — Manifest description non-empty
- Permissions declared (1 pt) — Permissions object not empty
- No security issues (2 pts) — No findings from security scan
- Permission extraction match (2 pts) — Extracted permissions ⊆ declared
- File count reasonable (1 pt) — Fewer than 100 files
- README documentation (1 pt) — README field non-empty
- Package size reasonable (1 pt) — Tarball under 5 MB
Data Model
Core Tables
Key Design Decisions
Why Supabase for Storage?
- OCI-compatible — Standard artifact storage pattern
- Content-addressable — Integrity built in via SHA-512
- Easy replication — Built-in CDN and edge caching
- On-prem abstraction — Provider interface supports self-hosted alternatives
Why 6-Stage Python Pipeline?
Custom analysis pipeline designed specifically for AI agent skills:- Stage-based isolation — Each stage can fail independently
- Deterministic output — Reproducible analysis results
- SARIF output — Standard vulnerability report format
- Incremental analysis — Cache results per stage
Why Lockfile?
Same reasons aspackage-lock.json:
- Deterministic installs — Same dependencies every time
- SHA-512 verification — Detect tampering
- Version resolution — Record resolved dependency tree
- Diffability — JSON with sorted keys for clean git diffs
Why Next.js for Registry?
- Unified codebase — Web UI + API in one app
- Server Components — Fast, SEO-friendly skill browsing
- Route Handlers — Clean REST API with TypeScript
- Vercel deployment — Zero-config production hosting
Performance
Tank enforces performance budgets via non-cached regression testing:- API routes — p95 latency targets (e.g.,
/api/v1/skills< 100ms) - Web routes — TTFB and FCP budgets
- CI gates — Merges blocked if performance regresses
Security Measures
- Install-time verification — SHA-512 hash checking
- Permission enforcement — Budget validation before install
- Static analysis — 6-stage security scanning
- Audit logging — All admin actions tracked
- Role-based access — Admin middleware for moderation
- Code signing (planned) — Sigstore integration in Phase 2
- Runtime sandbox (planned) — WASM isolation in Phase 3
Next Steps
Setup
Set up Tank for local development
Contributing
Learn how to contribute
Testing
Run and write tests