Skip to content

chore(startos): audit the package for community registry listing - #1

Merged
MattDHill merged 1 commit into
mainfrom
next
Jul 31, 2026
Merged

chore(startos): audit the package for community registry listing#1
MattDHill merged 1 commit into
mainfrom
next

Conversation

@helix-nine

Copy link
Copy Markdown

Full audit of the StartOS packaging layer ahead of a Community Registry listing. No application source is touched — everything here is under startos/, the build/CI plumbing, the package docs, and the icon.

What changed

SDK and build plumbing

  • @start9labs/start-sdk 1.5.3 → 2.0.9. The only source-level migration 2.0 needs here is dropping the await on SubContainer.of, which is now lazy and synchronous. The Makefile also loses its fallback shim for locating s9pk.mk — the SDK ships it since 2.0.6, so the Makefile is now the canonical two lines plus one documented recipe override.
  • One tsconfig instead of two. tsconfig.startos.json and startos/tsconfig.json were duplicates of each other. There is now a single startos/tsconfig.json that extends the SDK's tsconfig.base.json. It has to live inside startos/: the root tsconfig.json belongs to the React app and includes only src, and the SDK's ESLint runner uses projectService, which needs a project that actually contains startos/**/*.ts.
  • The SDK lint gate now runs. The previous javascript/index.js override skipped s9pk.mk's eslint step. npm run startos:lint is back in the recipe.
  • Packaging CI addedbuild.yml, release.yml, tagAndRelease.yml, targeting main.

⚠️ Tag-filter collision (please sanity-check this one)

This repo now has two release lanes tagging the same namespace:

Lane Tags Trigger
Desktop / Zapstore (scripts/release.sh) v5.7.0 desktop-release.yml
StartOS (tagAndRelease.yml) v5.7.0_0 release.yml

Left alone, the packaging template's v*.* would have fired the s9pk release on every desktop tag, and desktop-release.yml's v* would have fired a full Tauri build on every packaging tag (and then failed its own gate, since v5.7.0_0 doesn't match package.json). So release.yml filters v*_* and desktop-release.yml adds !v*_*. These two must stay in sync — noted in AGENTS.md.

Manifest, versions, i18n

  • packageRepohttps://github.com/Start9-Community/chama (this fork is the package repo). upstreamRepo still points at jesuspirate/chama.
  • Version 5.5.0:145.7.0:0: the upstream half tracks package.json, and the revision restarts at 0 because the upstream version moved. Nothing was ever published under the old string — chama is absent from both community registries — so this is a clean initial release.
  • i18n is now complete. translations.ts was an empty {} stub; it now carries es_ES, de_DE, pl_PL, fr_FR for every index, and the manifest description (short + long) and releaseNotes carry the same locales. Every user-facing string in main.ts, interfaces.ts and actions/ flows through i18n().

Runtime

  • Readiness was under-strict. It checked only the three web ports, so a client whose Fedimint bridge was down reported healthy while serving a page that 502'd every /bridge/ call. It now requires each client's bridge port too, and names the client in the failure message.
  • New action: Wallet Bridge Status (wallet-status, read-only, running-only). Reports per client whether the bridge answers, whether it has joined a federation, and its relay-discovery state. StartOS previously had zero visibility into the component that holds the money.
  • Interface copy reframed. The three interfaces were named and described as "isolated testing clients" in a package whose marketplace description sells a marketplace. They are now described as what they are — three self-contained clients, each with its own identity, browser storage and Fedimint wallet. The three-origin architecture itself is unchanged; it is deliberate and load-bearing.
  • nginx.conf: the same five-line proxy-timeout rationale was pasted into all three server blocks; it is stated once now.

Docs and assets

  • README.md is now the package README the packaging guide prescribes (centered logo, upstream callout, TOC, the full prescribed section set, AI-consumer YAML block, no version numbers anywhere). The app's build/architecture material is upstream documentation, so it is linked rather than duplicated.
  • instructions.md rewritten end-user-first: opens at ## Documentation, no install steps, no restatement of the marketplace description, no StartOS-platform explainers.
  • Added AGENTS.md, CLAUDE.md, UPDATING.md, TODO.md. CLAUDE.md was removed from .gitignore — every StartOS package repo carries it as a one-line @AGENTS.md import. Your other local agent-memory files (Codex.md, PHILOSOPHY.md, DECISIONS.md, INVARIANTS.md, BACKLOG.md, .claude/) stay ignored. Say the word if you'd rather keep CLAUDE.md local and I'll drop it.
  • icon.png 1024×1024 / 713 KB → 512×512 / 203 KB. A package icon is embedded as a base64 data URL in every registry index, and this was 3.4× the largest icon in the fleet. The Makefile rule that re-copied the full-size Tauri mark is gone; AGENTS.md records the one-line command to regenerate it.
  • assets/ABOUT.mdassets/.gitkeep. It was never mounted, so it shipped inside the .s9pk as dead weight.

Known limitation, documented not fixed

Neither the clients nor the bridges authenticate anyone. chama-fedimint-bridge refuses a non-loopback bind without --auth-token ("an unauthenticated bridge is a drainable wallet"), but here it is reached through nginx on the same origin as the page, so whoever can load a client interface can spend that client's ecash. A packaging-side token would be injected by the same nginx that serves the page, so it would add nothing. This is now stated in the README's Limitations, in instructions.md, and in TODO.md as something that needs an application-side fix.

Test plan

Built and verified on a real StartOS box (x86_64, StartOS 0.4.0-beta.10).

make x86          # builds the image and packs chama_x86_64.s9pk
make install      # sideloads onto the StartOS host

Then, on the box:

  1. Installs and starts. start-cli package listchama 5.7.0:0 installed; start-cli package start chama.
  2. Health goes green. start-cli db dump | jq .value.packageData.chama.statusInfo
    {"health":{"primary":{"name":"Web Clients","result":"success","message":"All three Chama clients are ready"}}}
  3. All six ports listen. start-cli package attach chama -n chama-sub -- cat /proc/net/tcp shows 0.0.0.0:8080/8081/8082 and 127.0.0.1:8787/8788/8789.
  4. All three interfaces serve the app. curl -k https://<host>:<assigned-ssl-port>/ on each → 200, <title>Chama — Bitcoin commerce for communities</title>.
  5. Each /bridge/ proxy reaches its own bridge. curl -k https://<host>:<port>/bridge/health on each → 200 with that bridge's health JSON.
  6. Per-client data directories exist and are separate. start-cli package attach chama -n chama-sub -- ls /dataclient-1 client-2 client-3, and each bridge runs with its own --data-dir.
  7. The action works. start-cli package action run chama wallet-status <<< 'null' → all three clients report Federation: Not joined yet (correct for a fresh install) and Relay discovery: Reachable.
  8. Fail-closed supervision works. Killing one chama-fedimint-bridge took the whole daemon down (primary daemon crashed), StartOS restarted it, all three bridges came back and health returned to All three Chama clients are ready.

The app's own gates also pass with the bumped dependency: npm run typecheck, npm test (all suites green), and npm run startos:check / startos:lint.

Not exercised: aarch64 (CI builds it), backup/restore, and a real federation join.

Packaging-layer only — no application source changes.

Plumbing
- start-sdk 1.5.3 -> 2.0.9. Drops the redundant `await` on the now-lazy
  `SubContainer.of`, and the Makefile loses its s9pk.mk fallback shim now that
  the SDK ships s9pk.mk itself.
- Collapses `tsconfig.startos.json` and `startos/tsconfig.json` into one file at
  `startos/tsconfig.json` extending the SDK's tsconfig.base.json. It has to live
  inside `startos/` — the root tsconfig belongs to the React app, and eslint's
  projectService needs a project that actually contains `startos/**/*.ts`.
- Runs the SDK's eslint gate (`startos:lint`), which the previous Makefile
  override silently skipped.
- Adds the three packaging workflows. Their tag filters and the desktop lane's
  are made mutually exclusive: `tagAndRelease` tags `v<version>_<revision>`,
  `scripts/release.sh` tags `v<version>`, and the template's `v*.*` /
  desktop's `v*` would each have fired on the other's tags.
- Adds AGENTS.md + CLAUDE.md, UPDATING.md and TODO.md; un-ignores CLAUDE.md,
  which every StartOS package repo carries as a one-line `@AGENTS.md` import.
- icon.png: 1024x1024/713K -> 512x512/203K. A package icon is embedded as a
  base64 data URL in every registry index, and this was 3.4x the largest icon
  in the fleet.

Manifest and versions
- packageRepo now points at this fork, which is the package repo.
- 5.5.0:14 -> 5.7.0:0. The upstream half tracks package.json (5.7.0) and the
  revision restarts at 0; nothing was ever published under the old string.
- description and releaseNotes gain es_ES, de_DE, pl_PL and fr_FR, and
  translations.ts is populated for all four instead of being an empty stub.

Runtime
- Readiness now requires each client's wallet bridge port as well as its web
  port. A client whose bridge is down still served its page and then 502'd every
  /bridge/ call while reporting healthy.
- Adds a read-only Wallet Bridge Status action reporting, per client, whether
  the bridge answers, whether it has joined a federation, and its relay
  discovery state — the only visibility StartOS had into the component holding
  the money was none.
- Reframes the interfaces: they were named and described as "isolated testing
  clients" in a package whose marketplace copy sells a marketplace.
- Drops the triplicated proxy-timeout comment in nginx.conf down to one.

Docs
- README.md is now the StartOS package README the packaging guide prescribes;
  app build/architecture material is upstream documentation and is linked, not
  duplicated. instructions.md is rewritten end-user-first, opening at
  Documentation.
- Both document the standing limitation that neither the clients nor the
  bridges authenticate anyone: the bridge's own non-loopback auth guard is
  bypassed by serving it through nginx on the page's origin, so whoever can
  load an interface can spend that client's ecash.
@MattDHill
MattDHill merged commit de8c299 into main Jul 31, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants