Manifest text is now carried through the solver's ResolvedPkg and written
directly to disk during install, eliminating the redundant re-fetch from
the repository that could silently fail. save_manifest() is now mandatory
(fatal on error) since the .p5m file on disk is the authoritative record
for pkg verify and pkg fix.
Add ADRs for libips API layer (GUI sharing), OpenID Connect auth, and
SQLite catalog as query engine (including normalized installed_actions
table). Add phase plans for code hygiene, client completion, catalog
expansion, and OIDC authentication.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge both the UI handler (index, ui modules) and the legacy pkg5
search endpoint changes. Remove the obsolete JSON-based
build_search_index method since search now uses FTS5 via
sqlite_catalog::build_shards.
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>
Replace the cramped FMRI badge and install-cmd div with full-width
copyable blocks that have labeled headers, single-line horizontal
scrolling (no wrapping), and a copy-to-clipboard button. The button
shows a checkmark on success. The install command copy strips the
leading $ prompt.
Read last-modified from catalog.attrs instead of using get_info() which
falls back to current time when the package directory scan finds nothing.
Widened publisher card grid min-width from 320px to 420px so the
formatted date doesn't get cut off.
Dependency FMRIs are version constraints (e.g. SUNWcs@0.5.11-151056.0)
not exact versions, so they don't match any specific manifest. Now
dependency links use the package name only, and the detail handler
resolves name-only or partial-version FMRIs by finding the latest
version from list_packages and redirecting to it.
The external CSS file wasn't loading on the deployed server despite
being embedded in the binary — likely a route matching or reverse
proxy issue. Moved all CSS into an inline <style> tag in the base
template. Since Askama compiles templates into the binary, this
guarantees the styles render with the HTML on first paint with zero
external dependencies. HTMX JS remains as an embedded route handler.
Static files (CSS, JS) were served via ServeDir using CARGO_MANIFEST_DIR
which only exists on the build machine, not on deployed servers. This
caused: white unstyled page, always-visible loading indicators, and
broken manifest loading.
- Embed style.css and htmx.min.js into the binary via include_str!
- Serve them from dedicated handlers with proper content-type and caching
- Move Google Fonts from CSS @import to <link> tags with preconnect
for non-blocking font loading
- Remove ServeDir dependency from routes
Fix package detail 404: FMRI in URL paths now uses just name@version
instead of the full pkg://publisher/name@version, since the publisher
is already a separate path segment. This affected package detail,
manifest loading, dependency links, and search result links.
Drop Pico.css CDN dependency — it was fighting the custom dark theme
causing visual issues. Replaced with a complete standalone stylesheet
with proper reset, giving full control over the design.
Design overhaul:
- Dark "Solaris Engineering" theme with amber accent colors
- JetBrains Mono + Source Sans 3 typography via Google Fonts
- Publisher cards with accent borders and stats layout
- Styled package tables with hover states
- Breadcrumb navigation and active nav indicators
- Colored dependency type badges (require/optional/incorporate)
- Terminal-style install command display
- Floating pill-shaped P5I cart with enter animation
- Custom scrollbars for manifest viewer
Bug fixes:
- P5I cart now hidden by default (was visible with 0 items)
- "Updated" timestamp now formatted via format_packaging_date
- Package count falls back to list_packages when get_info reports 0
Add a human-facing web interface at /ui/ for browsing IPS package
repositories. Uses Askama templates, HTMX for interactivity, and
Pico.css for styling.
Routes:
- /ui/ - Publisher list with package counts
- /ui/packages/:publisher - Paginated package list
- /ui/search - Search with HTMX search-as-you-type
- /ui/package/:publisher/*fmri - Package detail with lazy manifest
- /ui/p5i - P5I file generation for installing package sets
Multiple file actions in a manifest can reference the same payload hash.
When downloaded in parallel via rayon, multiple threads would write to
the same temp file path simultaneously, causing rename failures.
Now deduplicates payloads by digest before parallel download, then maps
results back to all file actions that reference each payload.
- Store compressed payloads under the primary (uncompressed) hash as
the main key, matching IPS protocol where clients request files by
the manifest's primary hash via /file/0/<hash>
- Create hardlink under compressed hash for internal lookups
- Detect SHA256 (64 chars) vs SHA1 (40 chars) from bare hex hash
length in Digest::from_str instead of always defaulting to SHA1
- Remove digest verification for local file copies in FileBackend
(files are compressed, hash is of uncompressed content)
- Simplify recv.rs payload fetch to use primary hash directly
instead of trying multiple digest formats against the source
Files were only stored under their compressed SHA256 hash, but pkg5
clients and the IPS protocol look up files by the manifest's primary
hash (typically SHA1/SHA256 uncompressed). Create a hardlink from the
primary hash path to the compressed hash file so both old and new
clients can find payloads via the server's /file/0/<hash> endpoint.
The previous digest fallback used Display format (source:algorithm:hash)
which caused REST servers to look up files by SHA256 compressed hash
instead of the expected SHA1 primary hash. Now tries raw hash first
(compatible with pkg5 REST servers), then formatted variants with
algorithm info (compatible with local FileBackend storage).
Multiple methods held a read or write lock on self.index while calling
fallback methods that also needed to acquire locks, causing deadlocks:
- get_obsoleted_package_metadata: read lock held during filesystem
fallback that calls update_index_entry (write lock)
- get_obsoleted_package_manifest: same pattern
- remove_obsoleted_package: write lock held while calling build_index
(also needs write lock)
- search_obsoleted_packages: read lock held during fallback
Fix: scope all lock acquisitions in blocks so locks are dropped before
calling any method that may also acquire a lock. For remove, extract a
needs_rebuild flag set inside the lock scope, then call build_index
after release.
All 95 libips tests now pass (previously 3 hung indefinitely).
- Use tempdir_in(repo_path) instead of system /tmp to keep temp files on
the same filesystem, preventing cross-device rename failures
- Replace fs::copy with fs::rename for atomic file moves in transaction
commit and signature payload storage
- Fix Digest construction to use correct SHA256 algorithm instead of
defaulting to SHA1 for bare hex hashes
- Try compressed hash (additional_identifiers) as fallback when primary
hash lookup fails during payload fetch
- Remove duplicate publisher resolution block in Transaction::commit()
- Add integration test for multi-file parallel package receive
Closes: https://codeberg.org/Toasterson/ips/issues/21
- Made `receive_one` public to allow external use.
- Improved signature payload fetching, storing, and fallback logic for `FileBackend` repositories.
- Added test case `test_receive_with_signature` to verify signature handling and repository storage.
- Extended manifest fields in transaction logic to support additional attributes (e.g., `users`, `groups`, `drivers`).
- Updated `RestBackend` to handle extended file path lookups for signature payloads.
- Added `resolve_packages` to centralize wildcard pattern processing and match the latest package versions consistently.
- Updated both `FileBackend` and `RestBackend` to support wildcard patterns via `glob_to_regex` logic.
- Made `glob_to_regex` public to facilitate regex conversion for glob patterns.
- Improved `catalog_manager` handling in `RestBackend` by explicitly loading catalog parts to ensure accurate package matching.
- Replaced redundant FMRI parsing logic with `resolve_packages` for cleaner and more maintainable code.
- Migrated `_SIGNATURE` handling in `CatalogPart`, `UpdateLog`, and `PackageUpdateEntry` to use metadata fields.
- Introduced `set_signature` and `signature` methods for cleaner access and manipulation of signature data.
- Updated deserialization logic to accommodate flattened metadata storage.
- Improved structure by centralizing signature and metadata interactions.
- Introduced specific error variants (e.g., `FileOpenError`, `FileWriteError`, `DirectoryCreateError`) in `RepositoryError` for better error diagnostics.
- Applied `.map_err()` handling for operations like file creation, copying, renaming, and directory manipulation.
- Replaced direct `HashMap` usage with `Mutex<HashMap>` for thread-safe access to catalog managers in `RestBackend`.
- Refactored `list_packages` to use `list_packages_from_catalog`, removing reliance on the search API.
- Added temporary directory management for non-local-cache scenarios in `RestBackend`.
- Implemented support for fetching, importing, and storing signature payloads during transaction creation.
- Added the `Signature` struct to represent signature-related action data.
- Updated `Manifest` to include and process `signatures` as part of its fields.
- Enabled signature file imports with proper path resolution in `pkg6repo`.
- Updated `FileBackend::open` calls to use immutable `repo` variables across multiple modules.
- Improved dependency action string construction by integrating optional properties, predicates, and facets for better clarity and flexibility.
- Eliminated LZ4-based compression and related decoding utilities for manifest handling.
- Removed unused private helper and legacy methods in `catalog.rs`.
- Standardized database path handling, replacing `catalog_db_path` and `obsoleted_db_path` with `active_db_path` and `obsolete_db_path`.
- Added `#[allow(dead_code)]` annotations for unused methods in `file_backend.rs` to reduce warnings.
- Introduced `CLAUDE.md` to provide detailed project documentation, including architecture, configuration, and implementation details.
- Added build and testing instructions, focusing on `cargo` commands and `cargo-nextest` for improved testing workflow.
- Described application modules (`settings`, `storage`, `jwks`, `web`) and key features like PKCE, WebAuthn, and 2FA.
- Covered OpenID Connect, OAuth 2.0 endpoints, and claims handling (AMR/ACR).
- Documented admin API, WebAuthn client setup, OIDC conformance, and migration steps for existing deployments.
- Transitioned the catalog backend from `redb` to `rusqlite` for better compatibility and concurrency.
- Updated `IpsProvider` to use SQLite for package querying, dependency resolution, and obsolescence handling.
- Removed `decode_manifest_bytes_local` and unused `manifest` cache logic.
- Simplified catalog-related functions and integrated `sqlite_catalog` module.
- Enhanced test functions and added schemas for managing SQLite databases.
- Introduced `.solstice/workflow.kdl` for defining Solstice CI workflows, including Linux and illumos builds.
- Added `setup-linux.sh` and `setup-illumos.sh` scripts for per-OS environment preparation.
- Implemented `job.sh` as a legacy script hook for additional build steps.
- Introduced `pkg6recv` for downloading packages from IPS repositories with support for recursive dependency fetching.
- Implemented CLI commands with `clap` for source/destination setup, package selection, and publisher defaults.
- Added `ConsoleProgressReporter` for detailed receive progress visibility.
- Enhanced the `Manifest` parser to support JSON format alongside IPS text format.
- Updated `FileBackend` and `RestBackend` repositories to fetch manifests and payloads in new operations.
- Extended `Digest` utilities for payload integrity checks.
- Added tests to verify basic functionality and manifest format preservation.
- Introduced scripts and configurations for manual testing using `anyvm` with OpenIndiana and OmniOS.
- Implemented repository fetching (`fetch_repo.sh`) and server startup (`run_depotd.sh`) scripts.
- Enhanced `pkg6depotd` to support default publisher routes and trailing slashes.
- Updated integration tests to verify new publisher route behavior.
- Replaced OpenIndiana VM with OmniOS VM in Illumos build steps across `rust.yml` and `release.yml` workflows.
- Updated related workflow labels and comments for consistency.