Files
Grant 257669092b v0.2.0:11 + v0.2.0:12 — Archive, Settings, agent surface, machines redesign
Two release cycles prepared together: v0.2.0:11 (policy archive + safe-
delete cleanup + brand-consistent confirm modals) and v0.2.0:12 (Settings
tab + agent-friendly operator API + machines tab redesign + buyer-facing
copy alignment).

Highlights:

- Migration 0015: policies.archived_at column. Archive button on tier
  cards; safe-delete relaxed to ignore revoked-license tombstones;
  renewal worker refuses archived policies.
- Migration 0016: scoped_api_keys table. Four roles (read-only,
  license-issuer, support, full-admin) with bounded scopes. Master
  admin_api_key still works on every endpoint; scoped keys gated on
  endpoints wired through require_scope().
- New /v1/openapi.json — public, no auth. Curated OpenAPI 3.1 spec
  for agent / SDK discovery.
- New Settings tab: Operator name + Payment providers panel + API
  keys management. Replaces 8 StartOS Actions (Zaprite all, BTCPay
  all, operator name, switch-provider). StartOS Actions pruned to 4
  install-time essentials.
- Machines tab rewritten: global default view grouped by product,
  filter pills with counts, quick-stats row, drill-down via new
  "Machines" button on each Licenses-tab row. New repo helper
  list_machines_admin joins machines x licenses x products
  server-side.
- Branded confirmModal replaces every native window.confirm() call
  in the admin UI (7 callsites).
- Enforce mode killed: KEYSAT_LICENSE_ENFORCE compile-time flag
  retired; daemon always boots; missing self-license -> Creator
  (free) tier. "Unlicensed" label gone from admin UI.
- Zaprite gated on the new zaprite_payments entitlement (renamed
  from card_payments to reflect the broader gateway).
- Creator code cap 5 -> 10.
- KEYSAT_AGENT_GUIDE.md: auth, role-to-scope mapping, error envelope,
  webhook events, worked recipes.
- Buyer-facing copy aligned with new positioning: "Bitcoin-native
  self-hosted software licensing" everywhere on production surfaces.
- Cross-product safety section (Section 9a) added to KEYSAT_INTEGRATION.md.
- 5 new API integration smoke tests covering OpenAPI, scoped API
  keys CRUD, role-elevation guard, and Zaprite-tier gating.

Test count: 83 passing (was 78). All migration tests pass against
0015 and 0016 applied to populated DBs.
2026-05-11 08:45:25 -05:00

38 lines
1.8 KiB
TypeScript

// Register actions with StartOS.
//
// The StartOS Actions tab is kept intentionally minimal — only the
// four operations that need to happen outside the admin web UI:
//
// - Set web UI password — needed for password recovery (you can't
// reset the password from inside the web UI if you can't log in)
// - Activate Keysat license — first-install bootstrap for paid
// customers, and recovery if /data/keysat-license.txt gets lost
// - Show license status — sanity-check the self-license state
// without logging into the admin UI
// - Show credentials — find the admin API key on first install,
// before you've logged into the admin UI for the first time
//
// Everything else — operator name, payment provider connect / activate,
// scoped API keys, products, policies, licenses, codes, machines,
// webhooks, audit log — lives in the embedded admin web UI under the
// Settings tab and the workspace sidebar. The action source files for
// those operations remain in this directory for reference, but they're
// no longer registered as StartOS UI buttons. This keeps the dashboard
// from feeling like an undifferentiated wall of buttons and aligns with
// "everything in one place" — the web UI.
import { sdk } from '../sdk'
import { activateLicense, showLicenseStatus } from './activateLicense'
import { setWebUiPassword } from './setWebUiPassword'
import { showCredentials } from './showCredentials'
export const actions = sdk.Actions.of()
// First-install / recovery essentials.
.addAction(setWebUiPassword)
.addAction(showCredentials)
// Keysat self-license (Keysat-licenses-Keysat). Required for paid
// customers to activate their self-license on first install. The
// license string itself is provided by your seller.
.addAction(activateLicense)
.addAction(showLicenseStatus)