Local discovery preferences and source previews
Private Settings accept aiConfigRoots, defaulting to an empty list for older catalogs. Each strict record contains an absolute/~/ configuration path (at most 4,096 characters) and one enumerated native provider format; at most twenty records are accepted. These records remain machine-local and outside portable library exports. They change read-only discovery, not project ownership or activation permission. GET /api/ai-config-roots inspects configured root metadata behind private HTTP access and reports origins/warnings; it does not read account stores or run a scan.
POST /api/sources/preview parses the existing bounded source input schema without network requests, catalog mutation or recipe execution. Saving still uses the ordinary sources operation and explicit online research behavior. Preview state in the UI is bound to the input/name/recipe fields and is hidden when those fields change. It is not source verification, a capability Snapshot or permission to Apply.
The existing browser AI preference record additionally retains model choices by runner. It holds only bounded model names, a runner and connection ID, not source input or prompts. Old single-model preferences remain readable; new native choices use the documented lightweight suggestions, with an explicit Provider default and custom-ID override.
AI connections and reviewed exports
Private Settings now have optional aiConnections (default empty, at most twelve distinct IDs) and the additional compatible AI runner. A connection contains id, name, baseUrl, model and apiKeyEnv, never the key value. Connection objects reject unknown fields. Credential reference names require the RIGSHELF_AI_ prefix and have a 100-character bound. Profiles are not included in portable library exports. AI draft requests accept a bounded connectionId; the service resolves one saved profile before scheduling generation. Requests cannot supply or override endpoint or authentication fields. A profile’s subsequent removal does not reroute its already started request. Browser preferences additionally remember the selected connection ID.
POST /api/backup-review accepts {} for a full export review or a bounded gzip portable archive for comparison. Comparison uses complete import validation without applying it and hashes schema-normalized record data. Canonical record ordering and export time do not affect the review fingerprint; metadata and resource changes do. Canonicalization refuses nesting beyond 32 levels. No remote destination, ownership or permission is adopted from the baseline.
GET /api/library-export?expected=<sha256> refuses a changed library before compressing the reviewed export. Legacy exports without expected remain available to existing explicit callers. The existing versioned portable archive format remains unchanged. No download is recorded as a remote backup receipt. See backup synchronization for remote publication and restore contracts.
Private ai-draft records hold explicit one-shot authoring requests, offered snapshot IDs, masked prompt data and validated proposals. They are bounded to 24 retained records, expire after 24 hours and are excluded from portable library exports. Waiting connected-Agent requests expire after 15 minutes; running generations have a two-minute deadline. Completion grants no library/project write authority. The optional aiModel setting defaults to an empty native-model choice; older settings continue to parse. Browser storage retains only Provider/model preferences, not AI request bodies. See AI assistance.
The private inventory supports optional aiFileLocations on projects and one shared global-ai-inventory record. Agent, Command, Config, Hook and Plugin metadata carries canonical location/root identity; native file bodies load on request. These are optional schema-1 additions excluded from portable library exports.
Immutable scan-baseline records contain a versioned gzip/base64 project/file index and installation relationships, with SHA-256 over decoded JSON. Capture reads and writes within one SQLite transaction before discovery mutations. Records omit original source-file contents and ownership/trust/automation grants. Input and decompressed content are bounded to 128 MiB. Settings lists the latest 50 summaries without pruning older records; selected downloads require private API access. These are inventory receipts, not full filesystem/catalog backups. Use a consistent SQLite backup for the complete private catalog.
The OS data directory contains catalog.sqlite and SQLite’s WAL companions. Directories are created with mode 0700 and the database with mode 0600. Use RIGSHELF_DATA_DIR to choose a different private location. Do not point it at a public checkout or shared web directory.
The default storage is ~/.local/share/rigshelf.
SQLite user_version and archive schemaVersion are 1. A newer database is refused. Future database changes require explicit migrations; future portable formats must retain an importer for schema 1 or provide an explicit migration. Record IDs are opaque and must not be inferred from display names.
An entry is a content-addressed snapshot with metadata, provenance receipts and supporting files. SHA-256 covers sorted file paths, exact base64 bytes and executable intent. A custom edit creates a revision with lineage; it does not mutate the upstream snapshot or installed pins. Archiving hides a snapshot from ordinary suggestions. Permanent deletion requires an archived record without installations or active plan references.
List metadata and reader responses omit the separately stored parsed mcp object. Explicit MCP body views mask sensitive environment values and recognized credentials, including historical definitions; the private Snapshot bytes and digest remain unchanged. Portable import/export, setup planning, applying setup plans and new automation approval validate the canonical body and require credential references. An unsafe historical definition needs a reviewed replacement Snapshot. Existing history is retained, and rollback still restores its recorded preimage.
Skill re-import merges existing authored tags/archive/source metadata and provenance in the same SQLite transaction as the snapshot write. If another connection commits after that transaction’s read, SQLite can refuse the stale promotion rather than overwriting those edits; retry reads the newer metadata. Snapshot bytes and supporting resources remain unchanged. This is atomic import reconciliation, not a claim that every legacy metadata editor has optimistic concurrency controls.
Sources hold URLs, preferred recipes, dated reachability, immutable upstream references, optional repository metadata and research notes. Changing a source relationship does not rewrite historical receipts. Presets use explicit IDs, single-parent inheritance, selectors, pins and exclusions. Directives have an explicit scope, priority, enable flag and provenance.
Presets and Directives are editable definitions; they are not immutable capability Snapshot histories. POST /api/presets and POST /api/rules create only and reject an existing ID within the save transaction. Explicit PUT retains the existing upsert contract for CLI/MCP clients. Preset graph validation and its saved event commit atomically; invalid inheritance leaves the prior graph unchanged. Display-name collisions in new UI records generate a distinct ID rather than implying replacement authority. Duplicate uses the currently edited fields and leaves the original definition intact.
Web edits use PATCH /api/presets/:id or PATCH /api/rules/:id with strict { value, expected } definitions. IDs must match the route. Schema-normalized expected fields are compared with current authored fields inside the same save transaction. A changed or removed record is refused without a success event or resurrection. Checked DELETE accepts { expected } and compares before removal; omitted checks retain the legacy explicit-deletion contract. This protects participating editors against stale overwrites, not against an explicitly authorized legacy PUT/delete, and is not revision history. Failed editor operations retain a copyable local draft; Preset Duplicate can preserve it separately.
Writable MCP save tools accept optional createOnly: true for a new definition or expected containing the previously read definition for a checked update. The two controls are mutually exclusive. Omitting both preserves the legacy explicit upsert. These operations change private definitions only; they do not enable project writes or automation on their own, and remain absent from default read/plan-only connections.
CLI save-preset and save-rule expose the same create-only behavior with --create-only and checked behavior with --expect previous.json. Both files use existing bounded regular-file reads. An invalid expected file, including JSON null, fails the checked operation rather than falling back to upsert. No new database/archive schema version or ownership record is introduced.
Definition ID collisions and stale expected checks return HTTP 409 with a fixed conflict message, without the newer record body. Malformed payloads still return 400. MCP expected values must be complete records read by ID: listing summaries omit pins/content and Rule content may be paginated/redacted. A partial or masked expected definition cannot substitute for the original authored fields.
Portable library
Portable archives have format: "rigshelf-library", schemaVersion: 1, exportedAt, entries, sources, presets, rules and an excluded report. An entry includes its files as canonical base64, without interpreting or extracting them. JSON is UTF-8; .json.gz is ordinary gzip of the same JSON. These are open formats suitable for user-managed encrypted backups or the GitHub/S3 backup transports.
Exports omit projects, installation paths, settings, access keys, local trust approvals, automation permissions, events, session data and plan preimages. Source notes, provenance and custom resources can still contain private information: exports are private user data, not a public registry. Credential heuristics exclude flagged snapshots or directives and identify their names/reasons. Preset references to excluded entries are removed in that export. Review the exclusion report; a backup with exclusions is intentionally incomplete.
Imports validate schema, canonical base64, exact digests, relative paths, unique records, supporting files, source references and preset cycles before one database transaction. Existing conflicting snapshots, presets or directives require reconciliation. Existing sources retain local edits. Matching immutable snapshots retain local tags, relationships and archive state. Re-adding a moved source URL finds or creates its own source instead of overwriting the moved record. Content is rescanned, and trust permissions are never imported. Imported origins and scans are evidence, not publisher verification.
Current bounds: 16 MiB and 2,000 files per skill; 128 MiB / 10,000 changed files per setup plan; 128 MiB compressed archive input; 512 MiB archive JSON; 256 MiB decoded imported resources. Source archives have separate 32 MiB compressed / 128 MiB decompressed / 20,000 repository-file bounds. Larger source collections can be imported as individual local skill folders. Ordinary JSON API requests are limited to 32 MiB. These limits are checked independently.
.rigshelf/kit.json in a project contains only the selected providers, entry pins, requirements, preset and managed hashes/MCP definitions. Private rollback preimages stay in the local catalog. Apply writes an exclusive lock and journal, verifies preconditions and atomically replaces each file. A failure compensates earlier writes. Rollback, and a compensated failure, also remove the directories that setup created when they are empty; directories that existed or appeared before Apply stay. After an interrupted process, rigshelf recover <plan-id> restores the state before that operation only when every file matches a known state. It also removes that operation’s interrupted temporary files and, for an interrupted Apply, the empty directories it created. Do not manually delete an unfamiliar write lock.
Global installations are observed, not removed. To reduce global context, first set up and verify project kits, then review global cleanup separately in the owning harness. Export/import does not automatically migrate credentials, global agent settings or conversations.
Private ownership records bind reviewed manifests to project directory identity. The project kit is portable desired state, not an authorization token. It cannot prove prior file ownership or grant automation on another machine. CLI record inputs use bounded regular-file reads before JSON parsing.
Project records may additionally contain documentLocations and inventoryWarnings. Document locations hold opaque IDs, local provenance, canonical paths, root identity, scope, harness, kind and read-only status; document bodies are not stored by discovery. These optional fields extend private record JSON without changing schema 1. Legacy project-relative documents remain readable through partial rescans. Projects and their enriched location metadata remain excluded from portable exports. See AI discovery for supported locations, exclusions and lazy-read checks.
Source groups are a display hierarchy over existing source IDs, not a migration or a new ownership record. Equal names or URLs do not merge independent relationships. Missing source metadata remains visible rather than dropping its entries. Snapshot revisions count once per existing item family; filtering happens before grouping and pagination. The browser’s version-1 library preference adds grouping: "source" | "none"; older or invalid values default to source grouping while retaining valid filters and saved views. Expansion and child-page state stay in the current view. No database or portable archive version changes.
Native Plugin entries can carry optional plugin metadata with format rigshelf-native-plugin-reference, native provider/ID, manifest type, component names and optional version/content hash. The JSON body is immutable and its digest remains SHA-256 of that body. Portable import validates typed metadata against the body. Installation records can carry private plugin evidence (installed, configured, local, cached, catalog), native ID, optional reported version, enabled flag and declared native scope. Paths/scopes and all installation relationships remain excluded from portable archives. Optional fields are additive to schema 1; legacy recipe entries remain readable. Repeated discovery preserves authored tags, source relationships, archive state and old Snapshot bodies/resources. Evidence across revisions is grouped for display; it does not imply activation or package safety. Browser version-1 preferences accept the optional evidence filter and default it to all for older saved views.
Project inspection can return previousSetup metadata from an existing private ownership record bound to the current directory identity: exact entry IDs, Harnesses, brief, Preset ID and whether the current regular, bounded manifest matches the reviewed bytes. It grants no new authority. The optional restorePrevious request flag defaults to false; opting in restores reviewed requirements/a still-available Preset for inspection, while ordinary explicit requirement updates stay independent. A copied repository manifest cannot create this private previous-setup state. Missing/changed/linked manifests remain a separate status and never enable automation. Existing schema-1 data and project manifests remain unchanged.
rigshelf_recommend exposes the same optional restorePrevious flag on a read/plan MCP connection. Use it for an unchanged returning brief; leave it false when supplying new requirements. The returned choices can seed an explicit plan, but reading/restoring them creates no plan, ownership, trust or automation grant.
Local workbench access and tab recovery
A private local-ui-access/main record stores a random 256-bit loopback API access key. It persists across restarts of the same catalog and is excluded from HTTP state, inventory checkpoints and portable exports. ui --reset-access rotates the key for future server instances; stop existing instances first because an already running server keeps its in-memory key until stopped. Binding failure does not create/rotate a key or start automation. A default port may advance through seven alternatives; an explicit port, or a reset attempt at an occupied default, is refused without stopping a listener.
rigshelf:project-draft:v1 is an optional bounded sessionStorage record in the current tab. It contains the directory, brief (at most 10,000 characters), Preset ID, known Harness IDs, at most 1,000 temporary exact Snapshot choices and a timestamp, within a 1 Mi-character serialization bound. Recovery can retain an oversized selection so the user can trim it; setup plans still accept at most 100 items. Parsing rejects malformed/oversized/unknown versions and constructs only these fields. It never restores a Plan ID, review acknowledgment, replacement consent, project approval or trusted-snapshot permission. Continue performs a fresh inspection; unavailable selections remain explicit and block review. Apply, a confirmed project replacement or Discard removes the recovery entry. Closing the tab may discard it. Storage failures are visible in the editable workspace. This is a small form-recovery record, not conversation memory or a cross-session history system.
Library’s current-project banner and exact-Snapshot handoff are in-memory UI context only. Each selection request binds to one project and is consumed once; an ambiguous path or different project cannot adopt it. No write plan, ownership, trust or automation permission comes from this context. Changes to shared guidance, Presets or the known project’s classification invalidate retained inspection before another review.
Manual POST /api/projects/:id/check accepts only an empty object and invokes dependency checking with automatic writes disabled. It uses a known private project record, preserves enriched inventory and updates the existing suggestion/project metadata without creating a plan or permission. Optional ProjectSuggestion fields retain the current record shape. Suggestions are still data until a separate reviewed setup.
HTTP inventory scans are owned background jobs. Workbench shutdown stops accepting requests, refuses new scan starts and waits for the active scan and its failure receipt before allowing catalog closure. It also settles AI, directory-picker and automation shutdown, retaining all failures rather than abandoning later operations after the first rejection. CLI scans still await the scanner directly. Graceful shutdown drains a scan; it does not claim immediate scan cancellation. Hard process/OS termination retains the existing checkpoint/SQLite recovery limits.
The server also retains the promises of active HTTP handlers, including mutations whose client has disconnected. Closing network connections does not substitute for settling those callbacks before catalog closure. Bun’s stop contract describes connection shutdown; an isolated runtime fixture confirmed that a gated callback can outlive stop(true). Closing refuses new handlers, settles the captured requests and owned jobs, then permits database closure. Unexpected server faults use fixed error responses and the same security headers rather than a runtime-generated diagnostic page.
Ollama model-list metadata is a bounded transient response, not a stored catalog record or model download. Its exact names, on-disk sizes and reported remote flag are used only for model selection; source hosts and other service internals are omitted. Request cancellation and deadline apply independently of generation lifecycle.
Remote backup records and authority
Destination profiles (backup-destination) are private catalog records, separate from Settings and portable exports. They contain a GitHub repository/branch/prefix or S3 endpoint/bucket/region/prefix, a private-bucket confirmation and credential variable names restricted to RIGSHELF_BACKUP_*. No secret value is stored. Profiles use checked full-definition updates. Physical destination identities prevent alias profiles from starting overlapping operations; display-name edits do not retarget a review.
A version-1 rigshelf-backup manifest indexes portable records by kind/ID and canonical SHA-256, includes exclusions and links the previous manifest digest. The gzip archive and canonical JSON manifest have independent content-addressed paths. current.json contains typed metadata and digests, never an arbitrary URL or filesystem path. Reading a manifest checks its content hash, unique record IDs and index fingerprint. Restore additionally checks compressed size/hash, bounded decompression, exact archived record fingerprint and complete portable import validation. Schema defaults do not rewrite historical hashes.
Private Sync reviews expire after 30 minutes. They bind local content, destination configuration, remote commit/ETag and deterministic artifact bytes. Private operation receipts survive interruption; owner/session identity, sequence checks and a per-destination lock coordinate processes. Sync has a three-minute operation deadline; network requests have a sixty-second deadline and refuse redirects. A failed response after a possible write remains uncertain. Retry requires explicit frozen-Snapshot acknowledgment and reuses the staged bytes/operation ID. Published/no-op receipts require a complete archive read and integrity check. An unmerged PR is pending. A receipt says what was observed; it cannot guarantee future remote retention.
backup-staging/<operation-uuid> holds immutable private 0600 archive/manifest/pointer files under 0700 directories. Interrupted and pending-PR operations retain them for exact retry. Confirmed success/cancellation removes only the three owned regular files and empty operation directory; changed/extra files are retained with a warning. Remote archives, manifests and PR branches are never pruned as compensation.
Restore reviews expire after 30 minutes and bind the selected immutable manifest and current local fingerprint. Default restore adds missing entries, sources, Presets and directives, preserving existing content/relationships and every local-only record. The explicit definitions mode can replace reviewed Presets/directives inside one SQLite transaction; immutable Snapshot conflicts still block. Validation and import writes share the same database reservation, so a concurrent authored definition cannot be overwritten between validation and mutation. Restore does not reconstruct Settings, project inventories, ownership, approvals, access keys or rollback preimages.