ips/CLAUDE.md
Till Wegmueller 745d610a0a
Rewrite CLAUDE.md for IPS project, remove Barycenter content
Replace the incorrectly copied Barycenter (OIDC IdP) content with
accurate IPS project documentation including workspace structure,
build commands, error handling conventions, architecture overview,
and a pkg5 legacy compatibility reference mapping our docs and
implementation to the original pkg5 specifications.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:18:43 +01:00

114 lines
7.3 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
IPS (Image Packaging System) is a Rust reimplementation of the illumos/OpenIndiana package management system (replacing the Python-based pkg5). It handles software packaging, installation, updates, and dependency resolution for illumos distributions.
**Workspace crates:** libips (core library), pkg6 (client CLI), pkg6repo (repo management CLI), pkg6depotd (HTTP depot server), pkg6recv, pkgtree, specfile, ports, userland, xtask.
## Build and Development Commands
```bash
cargo build # Build all crates
cargo check # Check without building
cargo nextest run # Run tests (CRITICAL: use nextest, not cargo test)
cargo nextest run test_name # Run specific test
make release # Build release + copy to artifacts/
RUST_LOG=libips=trace cargo run # Run with logging
```
**CRITICAL: Always use `cargo nextest run` instead of `cargo test`.** Tests need process isolation to avoid port conflicts.
## Coding Conventions
### Error Handling (miette + thiserror)
- All error enums derive `#[derive(Debug, Error, Diagnostic)]`
- Each variant has `#[diagnostic(code(...), help(...))]` with actionable guidance
- Subsystem errors chain via `#[error(transparent)] #[diagnostic(transparent)]`
- Return `IpsResult<T>` (alias for `Result<T, IpsError>`) from the top-level API
- Subsystem functions return their own result type (e.g., `RepositoryResult<T>`, `ImageResult<T>`, `FmriResult<T>`)
- Each module defines: `pub type Result<T> = std::result::Result<T, ModuleError>;`
- Diagnostic codes follow the pattern `ips::module::variant` (e.g., `ips::image_error::io`)
### Rust Style
- Use strongly typed idiomatic Rust — express logic in datatypes
- Do error handling — express options for how to handle issues for calling functions
- Use miette's diagnostic pattern to inform the user thoroughly what they need to do
- Never use raw SQL — use rusqlite with proper abstractions
- Edition 2024
## Architecture
### libips (core library)
- `fmri.rs` — FMRI parsing (`pkg://publisher/name@version`)
- `actions/` — Manifest action types (File, Dir, Link, User, Group, etc.) and filesystem executors
- `image/` — Image metadata, catalog queries, installed packages DB (SQLite)
- `repository/``ReadableRepository`/`WritableRepository` traits, FileBackend (local), RestBackend (HTTP)
- `solver/` — Dependency resolution via resolvo
- `digest/` — SHA1/SHA2/SHA3 hashing
- `payload/` — Package payload handling
- `publisher.rs` — Publisher configuration
- `transformer.rs` — Manifest transformation/linting
- `depend/` — Dependency generation and parsing
### Key Types
- `Fmri` — Fault Management Resource Identifier (`pkg://publisher/name@release,branch-build:timestamp`)
- `Manifest` — Collection of actions describing a package
- `Image` — Full or Partial image with metadata, publishers, catalogs
- `FileBackend` / `RestBackend` — Repository implementations
## pkg5 Legacy Documentation and Compatibility
We carry the original pkg5 reference documentation in `doc/pkg5_docs/` to guide compatibility with the legacy Python client. Our own docs in `doc/` describe how we've implemented the compatibility layer.
### Reference Specifications (from pkg5)
| Topic | File | What it covers |
|-------|------|----------------|
| **Depot protocol** | `depot.txt`, `depot.rst` | HTTP REST API: `/file/0/{hash}`, `/catalog/0/`, `/manifest/0/{fmri}`, `/search/0/`, `/p5i/0/`, `/publisher/0/`, `/versions/0/` |
| **Retrieval protocol** | `guide-retrieval-protocol.rst` | Client-depot wire protocol, ETag/If-Modified-Since caching, content negotiation |
| **Publication protocol** | `guide-publication-protocol.rst` | Transaction-based publishing (`open`, `add`, `close`) |
| **Repository format** | `guide-repository-format.rst` | On-disk layout: `pkg/`, `file/` (two-level hash dirs), `catalog/`, `trans/`, `updatelog/` |
| **Catalog v1** | `catalog-v1.txt`, `catalog.txt` | Delta-encoded text catalog with `catalog.attrs`, `npkgs`, incremental updates |
| **Actions** | `actions.txt`, `actions.rst` | All 12 action types: file, dir, link, hardlink, depend, service, user, group, driver, license, legacy, set |
| **FMRI & versioning** | `versions.txt`, dev-guide `chpt3.txt` | `pkg://publisher/name@release,branch-build:timestamp`, component ordering |
| **Image types** | `image.txt`, `image.rst` | Full, Zone, User images and their metadata layout |
| **Server API versions** | `server_api_versions.txt`, `client_api_versions.txt` | Protocol version negotiation between client and depot |
| **Signed manifests** | `signed_manifests.txt` | Manifest signature format and verification |
| **Linked images** | `linked-images.txt`, `parallel-linked-images.txt` | Zone/parent-child image constraints |
| **Facets & variants** | `facets.txt` | Conditional action delivery (`variant.arch`, `facet.doc`) |
| **Mediated links** | `mediated-links.txt` | Conflict resolution for symlinks across packages |
| **On-disk format** | `on-disk-format.txt` | Container format proposal for packages |
| **Dev guide** | `dev-guide/chpt1-14.txt` | Full IPS developer guide chapters |
### Our Compatibility Implementation
| Feature | Our doc | Implementation |
|---------|---------|----------------|
| **p5i publisher files** | `doc/pub_p5i_implementation.md` | `FileBackend` generates `pub.p5i` JSON files per publisher for backward compat with `pkg set-publisher -p` |
| **Obsoleted packages** | `doc/obsoleted_packages.md` | Detects `pkg.obsolete=true` during pkg5 import; stores in `<repo>/obsoleted/` with structured metadata |
| **pkg5 import** | `pkg6repo/src/pkg5_import.rs` | Reads `pkg5.repository`, two-level hash dirs, gzip payloads, URL-encoded versions; converts to pkg6 format |
| **Depot REST API** | `pkg6depotd/src/http/` | Serves same HTTP paths as pkg5 depot (`/file/0/`, `/manifest/0/`, `/catalog/0/`, `/publisher/0/`) |
| **libips integration** | `doc/forge_docs/ips_integration.md` | Typed API replacing pkg5 CLI tools (`pkgsend`, `pkgmogrify`, `pkgdepend`, `pkglint`, `pkgrepo`) |
| **Error handling** | `doc/rust_docs/error_handling.md` | miette + thiserror patterns with `ips::module::variant` codes |
### Key Compatibility Surfaces for Legacy Client
The legacy `pkg(1)` Python client expects these from a depot server:
1. **`/versions/0/`** — lists supported operations and protocol versions
2. **`/publisher/0/`** — returns `application/vnd.pkg5.info` (p5i JSON)
3. **`/catalog/0/`** — catalog with `Last-Modified` header, incremental updates
4. **`/manifest/0/{fmri}`** — `text/plain` manifest with `ETag`
5. **`/file/0/{hash}`** — gzip-compressed file content with `ETag` and `Cache-Control`
6. **`/search/0/{token}`** — search returning `index action value package` tuples
## Documentation Maintenance
- Keep `docs/ai/architecture.md` updated when making structural changes. Bump the "last updated" date.
- Create a new timestamped plan in `docs/ai/plans/` before starting a new phase or significant feature.
- Create a new timestamped ADR in `docs/ai/decisions/` when making meaningful technology or design choices. Number sequentially from the last ADR.
- Never delete old plans or decisions. Mark superseded plans with status `Superseded` and link to the replacement.