initial
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
# keysat-startos
|
||||
|
||||
StartOS 0.4.0.x wrapper package for [Keysat](../licensing-service) (the Rust daemon in `../licensing-service/`). This directory turns the upstream Rust daemon into an installable `.s9pk`.
|
||||
|
||||
The source directory is still called `licensing-service/` on disk for continuity; the binary it produces, the manifest id, and all operator-visible strings use the new name **Keysat**.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A working StartOS 0.4.0.x development environment (see [docs.start9.com](https://docs.start9.com)).
|
||||
- `start-cli` installed, with `~/.startos/developer.key.pem` initialized.
|
||||
- Node.js and npm (the StartOS SDK is TypeScript).
|
||||
- Docker (via buildx) for the multi-arch image build.
|
||||
|
||||
## Getting the shared build logic
|
||||
|
||||
The `Makefile` includes `s9pk.mk`, which is shared build boilerplate maintained by the Start9 team. Fetch it once:
|
||||
|
||||
```bash
|
||||
curl -o s9pk.mk https://raw.githubusercontent.com/Start9Labs/hello-world-startos/master/s9pk.mk
|
||||
```
|
||||
|
||||
(Or copy it from any other 0.4.0.x package you have locally.)
|
||||
|
||||
## Installing dependencies
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
## Building and installing
|
||||
|
||||
```bash
|
||||
# Build for all supported architectures
|
||||
make
|
||||
|
||||
# Or just the architecture of your dev StartOS box
|
||||
make arm # for Raspberry Pi / Apple Silicon StartOS
|
||||
make x86 # for an x86 StartOS server
|
||||
|
||||
# Push to your StartOS server (requires the developer key)
|
||||
make install
|
||||
```
|
||||
|
||||
`make install` will prompt for your StartOS password the first time; subsequent installs use the cached session.
|
||||
|
||||
## Project layout
|
||||
|
||||
This follows the standard 0.4.0.x layout:
|
||||
|
||||
```
|
||||
keysat-startos/
|
||||
├── Dockerfile # multi-stage Rust build
|
||||
├── Makefile # delegates to s9pk.mk
|
||||
├── s9pk.mk # (fetch from hello-world-startos)
|
||||
├── package.json / tsconfig.json
|
||||
├── icon.png # 512×512 StartOS tile
|
||||
├── assets/
|
||||
│ ├── ABOUT.md
|
||||
│ └── keysat-thumbnail.png # 1024×1024 marketing hero
|
||||
└── startos/
|
||||
├── manifest/index.ts # setupManifest()
|
||||
├── manifest/i18n.ts # descriptions, translatable
|
||||
├── main.ts # daemon definition
|
||||
├── interfaces.ts # network exposure (API on 8080)
|
||||
├── dependencies.ts # requires BTCPay Server
|
||||
├── actions/ # user-facing StartOS buttons
|
||||
│ ├── configureBtcpay.ts # one-click BTCPay authorize
|
||||
│ ├── createPolicy.ts # reusable license template
|
||||
│ ├── createProduct.ts
|
||||
│ ├── deactivateMachine.ts # force-kick an install
|
||||
│ ├── issueLicense.ts # comp / press keys
|
||||
│ ├── listMachines.ts # inspect a license's seats
|
||||
│ ├── listWebhooks.ts
|
||||
│ ├── registerWebhook.ts # outbound event subscriber
|
||||
│ ├── revokeLicense.ts # one-way permanent block
|
||||
│ ├── searchLicenses.ts # lost-key recovery
|
||||
│ ├── setOperatorName.ts
|
||||
│ ├── showCredentials.ts
|
||||
│ ├── suspendLicense.ts # reversible lockout
|
||||
│ ├── unsuspendLicense.ts
|
||||
│ └── viewAuditLog.ts
|
||||
├── fileModels/store.ts # persistent wrapper state
|
||||
├── init/index.ts # first-boot setup
|
||||
├── versions/ # migration history
|
||||
│ ├── index.ts
|
||||
│ └── v0.1.0.ts
|
||||
├── backups.ts # volume backup declaration
|
||||
├── sdk.ts # manifest-bound SDK instance
|
||||
├── utils.ts # small helpers
|
||||
└── index.ts # ties everything together
|
||||
```
|
||||
|
||||
## Dockerfile notes
|
||||
|
||||
The Dockerfile expects the `licensing-service/` source to be available at the parent directory (`..`). The manifest sets `images.main.source.dockerBuild.workdir` to `'..'` so `start-cli s9pk pack` runs `docker build` with the parent `Licensing/` directory as the context — Docker then sees the licensing-service source alongside this wrapper. A `.dockerignore` at the parent level keeps the uploaded context small.
|
||||
|
||||
If you're laying out the repositories differently — e.g., separate GitHub repos for service and wrapper — you'll want to add a git submodule or adjust the `workdir`/`COPY` paths accordingly.
|
||||
|
||||
## Operator workflow after install
|
||||
|
||||
1. Open the service in your StartOS dashboard.
|
||||
2. **Set operator name** → your display name, shown on the public homepage.
|
||||
3. **Connect BTCPay** → one-click authorize flow. Opens BTCPay's consent page in your browser; after you approve, the daemon auto-detects your store and registers its inbound webhook. No API keys to copy.
|
||||
4. **Check BTCPay connection** to confirm the authorize succeeded.
|
||||
5. **Create product** once per thing you want to sell.
|
||||
6. **Create policy** at least once per product, slugged `default`, to set the shape of keys issued through the public purchase flow (duration, grace period, entitlements, seat cap).
|
||||
7. Share the public service URL with buyers. That's enough for the standard purchase flow.
|
||||
|
||||
### Customer support
|
||||
|
||||
- **Search licenses** — look up a buyer by email, Nostr npub, or BTCPay invoice id.
|
||||
- **Suspend license** / **Unsuspend license** — reversible lockout (e.g., for payment disputes).
|
||||
- **Revoke license** — permanent, one-way kill.
|
||||
- **Issue license manually** — comp / press / grandfathered keys.
|
||||
- **List machines** — see which installs are bound to a license.
|
||||
- **Deactivate machine** — force-kick a specific install, freeing a seat.
|
||||
|
||||
### Integrations & operations
|
||||
|
||||
- **Register webhook endpoint** — POST signed event notifications to an HTTPS URL you control (license.issued, license.revoked, machine.activated, etc.). HMAC-SHA256 in `X-Keysat-Signature: sha256=<hex>`.
|
||||
- **List webhook endpoints** — see what's subscribed.
|
||||
- **View audit log** — most recent admin mutations, filterable by action slug. Useful for compliance and debugging.
|
||||
- **Show admin API key** — only needed if you want to script against `/v1/admin/*` from outside the box; every built-in action already carries the key for you.
|
||||
|
||||
## Limitations in v0.1
|
||||
|
||||
- No in-dashboard list view for invoices/products/licenses — use `/v1/admin/...` via the admin API key if you need a bulk view beyond what the built-in actions surface.
|
||||
- Webhook delivery retries are bounded; if a subscriber is down past the retry window, the event is dropped. Invoice reconciliation runs as a background task so dropped BTCPay webhooks get replayed.
|
||||
Reference in New Issue
Block a user