Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ npack is an independent package manager whose registry metadata will be publishe
- `npack update --check` (alias of `install-ref --check`) reports available updates for one or all installed packages without downloading or installing anything, the `apt update` counterpart to `update`'s `apt upgrade`.
- A manifest's optional `app` object (`summary`, `description`, `homepage`, `license`, `categories`, `icon`, `screenshots`, `desktop_file`, `release_date`) carries desktop-store metadata; `icon` and `desktop_file` are package-relative paths validated to exist and, for `desktop_file`, to be a syntactically valid freedesktop.org Desktop Entry file with `Exec` required when `Type=Application`.
- `npack appstream` maps a manifest's `app` metadata to an AppStream `<component>` document per the freedesktop.org AppStream spec: `console-application` when there is no `desktop_file` (advertising `<provides><binary>`), `desktop-application` otherwise (advertising `<launchable type="desktop-id">`). Component IDs are namespaced `io.npack.<publisher>.<name>` since publishers are Nostr pubkeys, not domains.
- `npack daemon` runs npackd, a local JSON-RPC-over-Unix-socket service (newline-delimited JSON requests/responses) exposing `Search`, `GetPackage`, `ListInstalled`, `Install`, `Remove`, `Update`, and `CheckUpdates` so a GUI store or other tool does not need to understand Nostr, Blossom, or `.npk` internals. It defaults to `$XDG_RUNTIME_DIR/npackd.sock` and handles connections concurrently via `tokio::spawn`. A client gets one response once an `Install`/`Update` call completes; transaction polling and progress-event streaming are future work.
- `npack daemon` runs npackd, a local JSON-RPC-over-Unix-socket service (newline-delimited JSON requests/responses) exposing `Search`, `GetPackage`, `ListInstalled`, `Install`, `Remove`, `Update`, `CheckUpdates`, `GetTransaction`, and `CancelTransaction` so a GUI store or other tool does not need to understand Nostr, Blossom, or `.npk` internals. It defaults to `$XDG_RUNTIME_DIR/npackd.sock` and handles connections concurrently via `tokio::spawn`. `Install`/`Update` run synchronously by default, or return `{"transaction_id": N}` immediately when called with `"async": true`, pollable via `GetTransaction`. `CancelTransaction` is cooperative: checked only between packages in a dependency graph or update loop, never mid-download or mid-install, so a cancelled transaction cannot leave the store half-installed. Progress-event streaming (as opposed to a final result) remains future work.
20 changes: 12 additions & 8 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ exposing:
Search() GetPackage()
ListInstalled() Install()
Remove() Update()
CheckUpdates()
CheckUpdates() GetTransaction()
CancelTransaction()
```

Chose a Unix socket over D-Bus for this first slice: no new system dependency
Expand All @@ -68,15 +69,18 @@ npackd handles connections concurrently (each accepted connection is
`tokio::spawn`ed), which required making the recursive dependency-install
future `Send`.

`Install`/`Update` run synchronously by default; passing `"async": true`
returns `{"transaction_id": N}` immediately, pollable via `GetTransaction`.
`CancelTransaction` is cooperative rather than raw task abortion: a shared
cancellation flag is checked only between packages (before starting the next
package in a dependency graph, or the next package in an `Update` loop),
never mid-download or mid-install of a package already in progress -- a
cancelled transaction cannot leave the store half-installed.

Remaining work:

- `GetTransaction()`/`CancelTransaction()` and streamed progress events for
long-running `Install`/`Update` calls -- a client currently gets one
response once the whole operation completes, with no way to poll status or
interrupt it partway through. A safe `CancelTransaction` needs a real
cooperative checkpoint in the install path (e.g. between packages in a
dependency closure, never mid-file-write) rather than raw task abortion,
which risks leaving the store in a half-installed state.
- Streamed progress events (e.g. per-file download progress) rather than a
single final result once `GetTransaction` reports the transaction done.

## Phase 3: Security and privilege separation

Expand Down
33 changes: 27 additions & 6 deletions docs/using-npack.md
Original file line number Diff line number Diff line change
Expand Up @@ -462,17 +462,38 @@ Supported methods, mirroring the CLI operations above:
| `Search` | `query`, `relay[]`, `trusted_publisher[]`, `pubkey`, `refresh`, `no_cache` | Array of matching releases. |
| `GetPackage` | `package`, `relay[]`, `requirement`, `os`, `arch`, `trusted_publisher[]`, `store`, `user` | The same resolved-metadata object as `npack resolve`. |
| `ListInstalled` | `user`, `store` | Array of installed packages. |
| `Install` | `package`, `requirement`, `relay[]`, `server[]`, `user`, `store`, `allow_capability[]` | The installed package's record. |
| `Install` | `package`, `requirement`, `relay[]`, `server[]`, `user`, `store`, `allow_capability[]`, `async` | The installed package's record, or `{"transaction_id": N}` if `async` is true. |
| `Remove` | `package`, `user`, `store` | `{"removed": "<package>"}`. |
| `Update` | `package` (omit for all), `relay[]`, `server[]`, `user`, `store`, `allow_capability[]` | Array of per-package update outcomes. |
| `Update` | `package` (omit for all), `relay[]`, `server[]`, `user`, `store`, `allow_capability[]`, `async` | Array of per-package update outcomes, or `{"transaction_id": N}` if `async` is true. |
| `CheckUpdates` | `package` (omit for all), `relay[]`, `trusted_publisher[]`, `user`, `store` | Array of `{reference, current_version, available_version}`. |
| `GetTransaction` | `transaction_id` | `{"status": "running"}`, `{"status": "succeeded", "result": ...}`, `{"status": "failed", "error": "..."}`, or `{"status": "cancelled"}`. |
| `CancelTransaction` | `transaction_id` | `{"cancel_requested": true}`. |

An unknown method or a request that fails to deserialize its params returns
`{"id": ..., "error": "..."}` instead of `result`. Each connection is handled
concurrently, but within a connection npackd does not yet stream
install/update progress back to the client; a client sees the final result
once the operation completes. GetTransaction/CancelTransaction-style progress
reporting is future work.
concurrently.

By default `Install` and `Update` run to completion before responding. Pass
`"async": true` to get `{"transaction_id": N}` back immediately and poll
`GetTransaction` for the final result:

```text
--> {"id": 1, "method": "Install", "params": {"package": "npub1.../myapp", "relay": ["wss://relay.example"], "async": true}}
<-- {"id": 1, "result": {"transaction_id": 1}}

--> {"id": 2, "method": "GetTransaction", "params": {"transaction_id": 1}}
<-- {"id": 2, "result": {"status": "running"}}
... later ...
--> {"id": 3, "method": "GetTransaction", "params": {"transaction_id": 1}}
<-- {"id": 3, "result": {"status": "succeeded", "result": {"publisher": "...", "name": "myapp", "version": "1.0.0", ...}}}
```

`CancelTransaction` is cooperative, not forcible: it is only checked between
packages (before starting the next package in a dependency graph, or the
next package in an `Update` loop), never mid-download or mid-install of a
package already in progress. This means a package that has already started
installing will finish before cancellation takes effect -- the store can
never be left half-installed by a cancelled transaction.

## Configuration

Expand Down
Loading
Loading