Implementation plan
Last updated: 2026-11-10. Scope reference: docs/SPEC.md.
Status labels used everywhere in this file:
- Implemented + tested — code exists and automated tests in
tests/exercise it. - Implemented — code exists; no dedicated automated test yet.
- Planned — not built. Nothing in the product may claim it.
- Rows updated on 2026-11-09 after the first production deployment (commit history has the details).
Nothing here is "live" until the deployment row of the acceptance table is filled in.
Phase 0 — Discovery and design
| Item | Status | Where |
|---|---|---|
Hosting constraints inspected (MacLustr, mld, tunnel, PostgreSQL 17 on node) |
Implemented | docs/OPERATIONS.md |
| Official standards checked (Agent Skills, MCP 2026-07-28, Claude Code, Codex, Cursor) | Implemented | docs/STANDARDS.md |
| Architecture decision records | Implemented | docs/adr/0001–0009 |
| Data model | Implemented + tested | packages/db/migrations/0001_init.sql |
| Threat model | Implemented | docs/THREAT_MODEL.md |
| Permission matrix | Implemented | docs/PERMISSIONS.md |
Visual system (tokens in globals.css; no separate wireframes were drawn) |
Implemented | apps/web |
| Inventory of the owner's existing packages | Planned | none published without approval |
Phase 1 — Working public registry
| Item | Status | Where |
|---|---|---|
| PostgreSQL schema, forward-only checksummed migrations | Implemented + tested | packages/db |
| Content-addressed blob storage, read-only blobs | Implemented + tested | apps/web/src/server/storage.ts, publish.test.ts |
| Read API: list, filter, search, categories, collections, artifact, versions, release detail, files, install instructions, checksum, download | Implemented + tested | apps/web/src/server/api.ts, publish.test.ts |
Usage examples: screenshots listed in the manifest (examples, up to 8, PNG/JPEG/WebP checked by header, 1.5 MiB each), served only from the release archive by GET …/versions/:version/media/*path, shown on the artifact page (grouped by client, full-size dialog) |
Implemented + tested | packages/registry-core/src/media.ts, validate.ts, apps/web/src/server/media.ts, components/examples-gallery.tsx; core.test.ts "usage examples", publish.test.ts "usage examples", tests/e2e/examples.spec.ts |
| Full-text search (tsvector, prefix, trigram fallback for queries of 5+ characters) | Implemented + tested | registry.ts |
| Semantic search | Planned | only with a measured relevance gain |
| OpenAPI 3.1 document generated from the route table | Implemented + tested | GET /api/v1/openapi.json |
| Download counting (daily aggregate, deduplicated, bot-filtered) | Implemented + tested | publish.ts |
| Homepage, explore, artifact pages, publisher profile, collections pages | Implemented + tested (E2E) | apps/web/src/app |
| Public docs and legal pages (content) | Implemented | apps/web/content |
English UI with strings structured for French (src/lib/i18n.ts; many page strings are still inline) |
Implemented | French translation itself is Planned |
| Demo seed data | Not applicable | no seed exists; production starts empty apart from real published artifacts |
Phase 2 — Authenticated publishing
| Item | Status | Where |
|---|---|---|
| Owner bootstrap, local console only, fails closed | Implemented + tested | auth.ts bootstrapOwner, tokens.test.ts |
| Single-owner database constraint | Implemented + tested | users_single_owner index |
| Email + password login (argon2id), database sessions, CSRF for cookie writes | Implemented + tested | auth.ts, api.ts |
| Step-up re-authentication (15 minutes) for token creation and rotation | Implemented + tested | tokens.test.ts |
| Scoped API tokens: create, list, revoke, rotate, expiry, namespaces, IP allowlist | Implemented + tested | auth.ts, tokens.test.ts |
| Elevated tokens (administrators only, 24 hours maximum) | Implemented + tested | tokens.test.ts |
| Namespace ownership checks on every write | Implemented + tested | publish.test.ts "namespace isolation" |
| Upload flow: begin, PUT bytes, finalize | Implemented + tested | publish.ts |
| Archive validation and static scanning | Implemented + tested | packages/registry-core, core.test.ts |
| Immutable releases (database triggers), revocation state | Implemented + tested | migration 0001, publish.test.ts |
| Quarantine and moderator review | Implemented + tested | publish.ts reviewRelease |
| Idempotency keys | Implemented + tested | api.ts |
| Append-only audit log with secret redaction | Implemented + tested | audit.ts, tokens.test.ts |
| Rate limiting and authentication-failure lockout | Implemented + tested | ratelimit.ts, tokens.test.ts |
Server console (pnpm admin …) |
Implemented | apps/web/scripts/admin.ts (services tested; the script wrapper is not) |
| CLI validate / pack / publish / dry-run | Implemented + tested (tests/integration/cli.test.ts) |
packages/cli |
| Publisher dashboard (artifacts, browser upload, tokens, audit, moderation, account) | Implemented + tested (tests/e2e/publisher.spec.ts) |
apps/web |
| Passkeys, OAuth sign-in, TOTP | Planned | auth_identities table exists for it |
| Self-service sign-up and email verification by mail | Planned | accounts are created by the operator |
| Per-namespace storage quotas | Planned | per-archive limits are enforced |
| Malware scanning (signature based) | Planned | static pattern scanner only |
Phase 3 — Agent integration
| Item | Status | Where |
|---|---|---|
| Install adapters (instructions and config snippets) for Claude Code, Codex, Cursor, generic Skills, generic MCP | Implemented + tested | packages/registry-core/src/install.ts, core.test.ts |
| Typed SDK | Implemented | packages/sdk (typechecked; exercised through CLI tests when they land) |
| Registry MCP server (Streamable HTTP tested with the official client; stdio entry implemented, not covered by a test) | Implemented + tested (tests/integration/mcp.test.ts) |
apps/registry-mcp |
| CLI install / update / download with checksum verification and rollback copy | Implemented + tested (cli.test.ts) |
packages/cli |
Example artifacts (published in production as @spboucher/hello-skill, citation-check, echo-mcp-server) |
Implemented + tested | examples/ |
| OAuth 2.1 authorization for the MCP endpoint | Planned | static bearer tokens in V1 |
| CLI published to npm with reproducible build provenance | Planned | runs from the repository in V1 |
Phase 4 — Community and trust
| Item | Status | Where |
|---|---|---|
| Abuse reports without an account | Implemented + tested | community.ts, publish.test.ts |
| Moderation: takedown, restore, source verification, report resolution | Implemented + tested (verify-source, listing); Implemented (takedown, restore, resolve) | community.ts |
| Identity-verified namespaces | Implemented | set by the operator: pnpm admin verify-namespace |
| Editorial collections | Implemented | community.ts, pnpm admin collections seed |
| Organizations and memberships | Schema + authorization check only | no management surface; see docs/PERMISSIONS.md |
| Reviewer role | Schema only | grants nothing in V1 |
| Security advisories | Schema only | security_advisories table |
| Ownership transfers | Schema only | ownership_transfers table |
| Webhooks | Schema only | webhooks, webhook_deliveries tables |
| Appeals workflow | Planned | handled by email in V1 |
| Signed release metadata / provenance attestations | Planned | SHA-256 checksums always present |
Phase 5 — Research-grade extensions
| Item | Status |
|---|---|
| Evaluation-kit type, bundle type with locked dependency versions | Implemented + tested (type and validation rules) |
| Structured benchmark metadata, workflow graphs | Planned |
| Federated registry discovery | Planned |
Acceptance criteria (spec section 18)
| # | Criterion | Status | Evidence |
|---|---|---|---|
| 1 | A visitor can discover and inspect public Skills and MCP entries without signing in | Implemented + tested; verified in production 2026-11-09 (30 read-only E2E checks, desktop + mobile) | tests/integration/publish.test.ts "lets an anonymous visitor discover, inspect and download it" |
| 2 | A visitor can download a release and independently verify its SHA-256 | Implemented + tested | publish.test.ts (download hash equals metadata, X-Checksum-Sha256, /checksum) |
| 3 | Accurate, tested installation instructions for Claude Code and one other client | Implemented + tested. skills install into the Claude Code and Codex skill directories verified against production with a scratch HOME; MCP snippets are generated and unit-tested but were not executed inside each third-party client |
tests/unit/core.test.ts "install adapters"; publish.test.ts "serves tested install instructions" |
| 4 | Secure owner bootstrap without a committed credential | Implemented + tested; run in production 2026-11-09 (admin.bootstrap audit event; password delivered to a 0600 file, never printed) |
tests/integration/tokens.test.ts "owner bootstrap" |
| 5 | Issue a scoped Claude Code token, store it securely, publish, rotate, revoke | Implemented + tested; in production the token was piped from the server console into the macOS Keychain without being displayed, used to publish, rotated, and a probe token was revoked (401 token_revoked) |
tokens.test.ts "scoped API tokens" |
| 6 | Revoked or expired token cannot publish; no cross-namespace modification | Implemented + tested | tokens.test.ts "a revoked token cannot publish", "an expired token cannot publish"; publish.test.ts "namespace isolation" |
| 7 | Claude Code can validate, dry-run, upload, publish and verify via CLI/API | Implemented + tested (cli.test.ts); done in production for the three examples (dry run, publish, re-download and re-hash) |
publish.test.ts "vertical slice" |
| 8 | Public MCP can search and inspect; publishing tools need authentication | Implemented + tested; verified in production with the official MCP client (12 tools, anonymous write → 401, traversal → 400) | tests/integration/mcp.test.ts |
| 9 | Malicious archive cannot traverse paths, expose secrets, execute on ingestion or overwrite another package | Implemented + tested | core.test.ts "tar codec", "path safety", "static scanner"; publish.test.ts "hostile uploads" |
| 10 | Releases are immutable and their history auditable | Implemented + tested | publish.test.ts "refuses to republish or mutate an existing version", "publishes a new version and moves latest, keeping history" |
| 11 | Unit, integration and E2E tests pass; accessibility and mobile QA pass | Unit + integration: 108 passing. E2E: 38 passing locally (desktop + Pixel 7 viewport), including axe WCAG 2.1 A/AA on 8 public pages and the token page, and no horizontal overflow. Not covered: manual screen-reader pass, real iOS Safari | pnpm test |
| 12 | Docs, backups, monitoring, incident response, security contact present | Implemented. Daily backup at 04:50 (PM2 skills-maint) and restore drill run on 2026-11-09 (infra/restore-drill.sh). Monitoring is health endpoints + mld heal; no external uptime monitor or alerting yet |
docs/OPERATIONS.md, SECURITY.md |
| 13 | Production deployed at https://skills.spboucher.ai after DNS, TLS, secrets and approval | Deployed 2026-11-09 on M3U96b via mld (owner asked for the deployment and had set DNS; Let's Encrypt certificate through the Caddy gateway) |
mld status, /api/v1/health/ready |
Known limitations
- Single process. Rate limits and the authentication-failure lockout live in process memory; they reset on restart and do not coordinate across instances (ADR-0004).
- Blobs are on the node's filesystem, not in S3-compatible storage (ADR-0003). Durability depends on the backup job.
- The scanner is a static pattern matcher. It does not detect obfuscated malware and makes no safety guarantee.
- No email is sent. There is no self-service sign-up, password-reset mail or email verification by link; the operator creates accounts and resets passwords from the server console, and the bootstrap marks the owner's email as operator-attested.
- No second factor in V1.
- Organizations exist in the schema and in the authorization check, but cannot be created or managed through any interface.
compatibilityentries are publisher claims. Theverifiedflag exists but nothing sets it yet.- The whole archive is buffered in memory during finalize (20 MiB cap).
- Example images are read by unpacking the release archive in memory on first request, then kept in a per-process cache (96 MiB cap). Only image headers are checked; images are not decoded, re-encoded or resized, so the page loads them at full size.
- No CI pipeline yet; checks are run locally and at deploy.
- Docker Compose for local development is not provided; local development uses a local PostgreSQL.
Next milestones
- Done 2026-11-09: CLI, MCP server and web UI landed and the rows above carry their evidence.
- Deploy, run the bootstrap, issue the publisher token, publish the example artifacts with the owner's approval, verify criteria 1–13 against production.
- CI (typecheck, tests, dependency audit, secret scan).
- TOTP and passkeys for human accounts; self-service sign-up with email verification.
- OAuth 2.1 for the MCP endpoint.
- Organization management, ownership transfers, webhooks, advisories.
- S3-compatible storage driver and off-site blob replication.