pakstr 0.29.1 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/android-template/app/src/debug/AndroidManifest.xml +5 -2
- package/android-template/app/src/main/AndroidManifest.xml +1 -0
- package/desktop-runtime/README.md +108 -0
- package/desktop-runtime/dist/main.js +22211 -0
- package/desktop-runtime/dist/preload.js +53 -0
- package/dist/cli.js +17 -3
- package/dist/commands/build.js +1 -0
- package/dist/commands/buildDesktop.js +140 -0
- package/dist/desktop/common/artifacts.js +16 -0
- package/dist/desktop/common/asar.js +60 -0
- package/dist/desktop/common/electron.js +50 -0
- package/dist/desktop/common/files.js +30 -0
- package/dist/desktop/common/fuses.js +62 -0
- package/dist/desktop/common/packager.js +46 -0
- package/dist/desktop/linux.js +425 -0
- package/dist/desktop/macos.js +125 -0
- package/dist/desktop/stage.js +117 -0
- package/dist/desktop/windows.js +384 -0
- package/dist/desktop/zip.js +204 -0
- package/dist/shared/nip46Pairing.js +278 -0
- package/package.json +14 -3
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ The CLI API and configuration format may change before 1.0.0.
|
|
|
19
19
|
|
|
20
20
|
## Requirements
|
|
21
21
|
|
|
22
|
-
* **Node.js** 22+
|
|
22
|
+
* **Node.js** 22.12+
|
|
23
23
|
* **Docker Desktop**
|
|
24
24
|
|
|
25
25
|
*Note: No Android SDK, Gradle, Java, or Android keystore setup is required locally.*
|
|
@@ -67,6 +67,16 @@ npx pakstr run
|
|
|
67
67
|
* `npx pakstr delete --publisher` — Inventory every event authored by the configured publish nsec; add `--execute` for the publisher-wide NIP-09 deletion request.
|
|
68
68
|
* `npx pakstr run` — Execute the full pipeline at once (**build** + **sign** + **publish**).
|
|
69
69
|
|
|
70
|
+
### Desktop (macOS arm64, Windows x64, Linux x64, experimental)
|
|
71
|
+
|
|
72
|
+
`pakstr build --target macos-arm64` packages the same `pakstr.yaml` app as `<appName>.app` in `<appId>-macos-arm64.zip` next to `build.out`. It runs on macOS only and downloads the pinned Electron release on first use. The app is ad-hoc signed and **not notarized**: Gatekeeper rejects it once downloaded, so it is for local testing only. App data lives in `~/Library/Application Support/<appId>`.
|
|
73
|
+
|
|
74
|
+
`pakstr build --target windows-x64` writes `<appId>-windows-x64-setup.exe`, a per-user installer (no admin rights; installs to `%LOCALAPPDATA%\Programs\<appId>` with a Start menu shortcut and an uninstaller), and `<appId>-windows-x64.zip`, a portable `<appName>\<appName>.exe` folder. It builds on any host with [NSIS 3](https://nsis.sourceforge.io/) (`makensis`) on `PATH` (`brew install makensis`, `apt install nsis`, or the Windows NSIS installer). Both are **unsigned**, so SmartScreen warns before the first run. The numeric part of `versionName` becomes the Windows file version. App data lives in `%APPDATA%\<appId>` and survives uninstall.
|
|
75
|
+
|
|
76
|
+
`pakstr build --target linux-x64` writes `<appId>-linux-x64.AppImage` and `<appId>-linux-x64.zip`, a portable `<appName>/<appId>` folder that keeps its executable bits. It builds on macOS or Linux (not Windows) with squashfs-tools 4.5+ (`mksquashfs`, `unsquashfs`) on `PATH` (`brew install squashfs`, `apt install squashfs-tools`), and downloads the pinned Electron release and AppImage runtime on first use. The icon comes from the same `logo.png` / `app.icon` lookup as Android. Running the AppImage needs FUSE 3, and Chromium's sandbox needs unprivileged user namespaces; Pakstr never turns the sandbox off, so distributions that restrict them (Ubuntu 23.10+) need an AppArmor profile or an administrator-installed package. App data lives in `~/.config/<appId>`.
|
|
77
|
+
|
|
78
|
+
Desktop publishing and other platforms are not supported yet; `sign`, `publish`, and `run` remain Android-only.
|
|
79
|
+
|
|
70
80
|
Delete commands are non-destructive by default. `--app` and `--publisher` are mutually exclusive, and Blossom HTTP deletion requires `--app --execute --delete-blobs`. NIP-09 is best-effort: relay acceptance does not prove physical erasure, and discovery is limited to events retained and returned by the configured relay.
|
|
71
81
|
|
|
72
82
|
---
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
-
|
|
2
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
3
|
+
xmlns:tools="http://schemas.android.com/tools">
|
|
4
|
+
<application
|
|
5
|
+
android:memtagMode="sync"
|
|
6
|
+
tools:replace="android:memtagMode">
|
|
4
7
|
<activity-alias
|
|
5
8
|
android:name=".debug.DeveloperToolsDebugLauncher"
|
|
6
9
|
android:enabled="true"
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
android:fullBackupContent="@xml/backup_rules"
|
|
24
24
|
android:icon="@mipmap/ic_launcher"
|
|
25
25
|
android:label="@string/app_name"
|
|
26
|
+
android:memtagMode="async"
|
|
26
27
|
android:networkSecurityConfig="@xml/network_security_config"
|
|
27
28
|
android:roundIcon="@mipmap/ic_launcher_round"
|
|
28
29
|
android:supportsRtl="true"
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Pakstr desktop runtime
|
|
2
|
+
|
|
3
|
+
Electron runtime that hosts a Pakstr web app on desktop, mirroring the Android
|
|
4
|
+
shell's contracts. `pakstr build --target macos-arm64|windows-x64|linux-x64`
|
|
5
|
+
stages this bundle with the app (`src/desktop/` in the CLI); the bundle ships
|
|
6
|
+
in the CLI's npm package. All targets package the same bundle; only the menu
|
|
7
|
+
differs (`src/appMenu.js`).
|
|
8
|
+
|
|
9
|
+
## Build
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm --prefix packages/cli ci
|
|
13
|
+
npm --prefix packages/cli run build # tsc, then bundles dist/main.js and dist/preload.js
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`npm --prefix packages/cli/desktop-runtime install` is only needed to run the
|
|
17
|
+
runtime unpackaged with the `electron` dev binary.
|
|
18
|
+
|
|
19
|
+
`dist/main.js` and `dist/preload.js` are self-contained: only `electron` and
|
|
20
|
+
Node built-ins are left external (the build fails otherwise), so a generated
|
|
21
|
+
app needs no `node_modules`. Third-party code and `src/shared` come from the
|
|
22
|
+
CLI package. The `debug` package is compiled out because applesauce logs
|
|
23
|
+
NIP-46 request params through it.
|
|
24
|
+
|
|
25
|
+
## Generated app layout
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
<appRoot>/package.json "main" -> the bundled main.js (preload.js beside it)
|
|
29
|
+
<appRoot>/pakstr-desktop.json { "appId": "com.example.app", "appName": "Example" }
|
|
30
|
+
<appRoot>/web/ staged web assets, incl. pakstr-runtime.json
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Behaviour
|
|
34
|
+
|
|
35
|
+
- The app is served from `pakstr://app` (standard, secure scheme) with the
|
|
36
|
+
Android SPA fallback. `/api/*` is proxied to the effective API base
|
|
37
|
+
(persisted override, then packaged `apiBase`, then disabled). API cookies
|
|
38
|
+
live in the session cookie jar and never reach the renderer, and neither
|
|
39
|
+
do `Set-Cookie` or `Location`. Redirects are not followed.
|
|
40
|
+
- NIP-98: `X-Forwarded-Host: app` / `X-Forwarded-Proto: pakstr` are added
|
|
41
|
+
only when the event's unique `u` tag is exactly the local request URL.
|
|
42
|
+
- `window.nostr` (plain and writable, like `nip07.js`) and the synchronous
|
|
43
|
+
`window.PakstrBridge.getApiBaseUrl()` / `setApiBaseUrl(url)` exist only in
|
|
44
|
+
the main window's `pakstr://app` top frame. The first `window.nostr` call
|
|
45
|
+
without a signer opens a `nostrconnect://` pairing prompt that uses the
|
|
46
|
+
strict `src/shared/nip46Pairing` module.
|
|
47
|
+
- All renderers are sandboxed with context isolation. Top-level navigation
|
|
48
|
+
stays on `pakstr://app`, `window.open` is denied, and web permissions are
|
|
49
|
+
denied except clipboard write and fullscreen. DevTools are available only
|
|
50
|
+
when unpackaged, and a packaged app exits if launched with a
|
|
51
|
+
remote-debugging or certificate-bypass switch. The runtime never disables
|
|
52
|
+
Chromium's sandbox.
|
|
53
|
+
- All data (cookies, storage, API base override) lives in
|
|
54
|
+
`<appData>/<appId>`. The Electron app name is also the appId, because it
|
|
55
|
+
names the keychain item holding the cookie-encryption key ("<name> Safe
|
|
56
|
+
Storage"): renaming `appName` keeps sessions. The macOS menu shows `appName`.
|
|
57
|
+
|
|
58
|
+
## Windows: not yet verified on a Windows machine
|
|
59
|
+
|
|
60
|
+
Windows packages are cross-built and checked structurally (executable
|
|
61
|
+
metadata, fuses, asar integrity, portable ZIP contents, NSIS output), but
|
|
62
|
+
nothing here runs them. Before relying on `windows-x64`, check on real Windows
|
|
63
|
+
10/11 x64:
|
|
64
|
+
|
|
65
|
+
- The installer runs without admin rights. The Start menu shortcut, the
|
|
66
|
+
Apps & features entry, and the finish-page launch work, and uninstalling
|
|
67
|
+
removes everything except `%APPDATA%\<appId>`.
|
|
68
|
+
- Reinstalling or upgrading over a running app prompts to close it, and an
|
|
69
|
+
upgrade that renames `appName` leaves no old `.exe` or shortcut behind.
|
|
70
|
+
- The portable ZIP runs after extraction, including from a path with spaces
|
|
71
|
+
or non-ASCII characters.
|
|
72
|
+
- The app starts with the asar-integrity and `OnlyLoadAppFromAsar` fuses on.
|
|
73
|
+
`pakstr://app` loads, `/api` proxying, cookies (DPAPI), `window.nostr`,
|
|
74
|
+
NIP-46 pairing, and signer auth links work, and a second launch focuses the
|
|
75
|
+
first window.
|
|
76
|
+
- Taskbar pinning: Electron's default AppUserModelID may not match the
|
|
77
|
+
installer's shortcut (it has no AUMID), so a pin from the Start menu can
|
|
78
|
+
show as a separate taskbar button.
|
|
79
|
+
- SmartScreen shows the unsigned-publisher warning; there is no Authenticode
|
|
80
|
+
signing yet.
|
|
81
|
+
|
|
82
|
+
## Linux: not yet verified on a Linux machine
|
|
83
|
+
|
|
84
|
+
Linux packages are cross-built and checked structurally (pinned AppImage
|
|
85
|
+
runtime, root-owned squashfs with exact modes, desktop entry, icon, portable
|
|
86
|
+
ZIP modes, fuses, asar hashes), but nothing here runs them. Electron enforces
|
|
87
|
+
embedded asar integrity on macOS and Windows only, so on Linux the read-only
|
|
88
|
+
AppImage filesystem and the build-time checks are what protect `app.asar`.
|
|
89
|
+
Before relying on `linux-x64`, check on real x64 distributions (e.g. Ubuntu
|
|
90
|
+
22.04 and 24.04, Fedora, Debian 12):
|
|
91
|
+
|
|
92
|
+
- The AppImage starts with FUSE 3 (`fusermount3`), and with
|
|
93
|
+
`--appimage-extract-and-run` without FUSE; the portable ZIP runs after
|
|
94
|
+
`unzip`, including from a path with spaces.
|
|
95
|
+
- Chromium's sandbox: with unprivileged user namespaces available the app
|
|
96
|
+
starts sandboxed. Where they are restricted (Ubuntu 23.10+ AppArmor) it
|
|
97
|
+
is expected to abort rather than run unsandboxed; record the message. The
|
|
98
|
+
runtime never passes `--no-sandbox`, and `chrome-sandbox` is not setuid.
|
|
99
|
+
- `pakstr://app` loads, `/api` proxying, `window.nostr`, NIP-46 pairing, and
|
|
100
|
+
signer auth links (`xdg-open`) work, and a second launch focuses the first
|
|
101
|
+
window.
|
|
102
|
+
- Cookies are encrypted with the desktop keyring (Secret Service / KWallet);
|
|
103
|
+
without one, Chromium falls back to a fixed key, so check which backend is
|
|
104
|
+
used.
|
|
105
|
+
- The window class / Wayland app id is the appId, so desktop integration
|
|
106
|
+
(AppImageLauncher, appimaged) groups the window with the desktop entry and
|
|
107
|
+
shows the icon. Required system libraries (GTK 3, NSS, libgbm, ALSA, ...)
|
|
108
|
+
are those of any Chromium build and are not bundled.
|