Skip to content

chore: migrate to start-sdk 2.0 - #24

Merged
helix-nine merged 10 commits into
mainfrom
next
Jul 23, 2026
Merged

chore: migrate to start-sdk 2.0#24
helix-nine merged 10 commits into
mainfrom
next

Conversation

@helix-nine

@helix-nine helix-nine commented Jul 4, 2026

Copy link
Copy Markdown

start-sdk 2.0 migration

Migrates this package to @start9labs/start-sdk 2.0 (requires StartOS 0.4.0-beta.10).

Changes

  • SDK pin → 2.0.1, TypeScript → ^6, tsconfig.json extends the shipped tsconfig.base.json, Makefile includes the SDK's s9pk.mk (vendored copy removed), reusable CI workflows repointed to Start9Labs/start-technologies.
  • 2.0 API migrations: sdk.serviceInterface.*sdk.host.* resolved over the LXC bridge, lazy SubContainer, alerts manifest field removed, and other ### Changed / ### Removed items from the SDK 2.0 changelog.

Upstream submodule sync

  • Advances the upstream/ submodule (Alex71btc/lndk-pay) to latest main (bec0899). The SDK-2.0 migration commit had inadvertently reverted the gitlink to e9707a1 ("Release v0.2.111"); this restores it and brings the branch level with — and one commit past — main's ea7432f pin.
  • Recovered upstream changes since e9707a1: LND 0.21 RouterRPC payment fixes, CSRF fix for LNURL payments, native onion-messaging detection for LND 0.21+, server-side SQLite offer history + BIP353 management, copy support for payment results, and LNURL translation fixes.
  • npm update refreshed the transitive #next git-ref deps (lnd-startos, bitcoin-core-startos).
  • StartOS version stays 0.2.116:2 — the substantive upstream content (through ea7432f) is already what main labels 0.2.116; the only newer commit (bec0899) is a root-README edit that never reaches the image. packageRepo is already canonical (Start9-Community/bolt12-pay-startos).

Test plan

  • CI build is green (npm citsc → SDK lint → nccs9pk pack).
  • Install the built 0.2.116:2 .s9pk on a StartOS 0.4.0-beta.10 server that already has LND 0.21.0-beta+ installed and unlocked.
  • Start BOLT12 Pay; confirm it reaches its health check and its web UI loads on the LAN interface, and that it connects to LND over the LXC bridge (LND REST + gRPC, reading TLS cert + admin macaroon from the read-only /mnt/lnd mount).
  • Create a BOLT12 offer, then pay a BOLT12 offer; confirm the payment succeeds on LND 0.21 (RouterRPC fee-limit fix) and the payment result can be copied.
  • Confirm no Auto-Configure / onion-messages setup task is present (native onion messaging in LND 0.21 is used instead).
  • Upgrade from a prior 0.2.116 install; confirm the SQLite offer history is preserved and the service restarts cleanly.

🤖 Generated with Claude Code

@helix-nine helix-nine changed the title chore: migrate to start-sdk 2.0 chore: migrate to start-sdk 2.0; sync upstream submodule to latest Jul 4, 2026
@Alex71btc

Copy link
Copy Markdown

Hey @helix-nine , @MattDHill, I have one concern about removing the Auto-Configure task completely.

While LND 0.21 no longer needs the protocol.custom-message entries (and they actually cause the "feature bit 39 already set" error), BOLT12 Pay is still fully compatible with LND 0.20.x.

I expect many node operators to stay on LND 0.20 for quite some time after the 0.21 release, especially larger routing nodes that tend to upgrade conservatively.
If we require LND >=0.21, those users won't be able to install or update BOLT12 Pay anymore, even though it works perfectly with 0.20.

Wouldn't it make more sense to keep the Auto-Configure task but make it version-aware?

show/run the task only for LND < 0.21
hide/disable it completely for LND >= 0.21
That way we keep backward compatibility while avoiding the configuration conflict on newer LND versions. It seems like the best user experience and allows a smoother transition to 0.21.

The application itself doesn't depend on 0.21, it runs with both versions — only the configuration step changes.

@MattDHill MattDHill changed the title chore: migrate to start-sdk 2.0; sync upstream submodule to latest chore: migrate to start-sdk 2.0 Jul 12, 2026
@helix-nine

Copy link
Copy Markdown
Author

@Alex71btc You're right, and thanks for catching it — I've dropped the LND 0.21 requirement. Pushed in 235828b.

Your reasoning holds on both counts. BOLT12 Pay genuinely does run against LND 0.20 (only the configuration step differs, not the app), and StartOS 0.4.0 keeps running packages built against the pre-2.0 SDK — so an operator can absolutely be sitting on LND 0.20.1-beta:13 on a 0.4.0 server and stay there. Requiring >=0.21 would have locked exactly those users out of installing or updating, for no functional gain. That was my error, not a deliberate call.

What changed

Implemented as you suggested — the task is kept and made version-aware, rather than removed:

  • Dependency floor back to >=0.20.1-beta:12 (was >=0.21.1-beta:0).
  • startos/dependencies.ts reads LND's installed version and posts the hidden autoconfig task only to nodes below 0.21.0-beta:0. On 0.21+ it isn't posted, and any existing one is cleared.

One wrinkle worth flagging, since it shapes the implementation: LND 0.21 doesn't just ignore the old keys — it removes the onion-messages toggle from its config spec entirely, and force-strips protocol.custom-message / custom-nodeann / custom-init from lnd.conf (they make 0.21 abort server creation with feature bit: 39 already set and crash-loop). Two consequences:

  1. The upgrade path had to be handled explicitly. A 0.20 user who satisfies the task and later upgrades to 0.21 would have had lnd.conf stripped, re-firing the input-not-matches trigger forever — a critical task demanding a toggle that no longer exists. So the version is read reactively via sdk.getServiceManifest(...).const(): upgrading LND re-runs init and clears the task instead of stranding the user.

  2. The task is posted through the raw effects.action.createTask rather than sdk.action.createTask. The typed autoconfig action we import is 0.21's, and it can no longer describe an onion-messages field. The raw effect takes the OS's untyped TaskInput and derives the same replayId the SDK helper would (lnd:autoconfig), so behavior is identical — it's the same call one level down.

Net effect:

Installed LND Onion messages Auto-Configure task
>=0.21.0-beta:0 Native (feature bit 39) Not posted; cleared if present
<0.21.0-beta:0 Need the protocol.custom-* entries Posted as critical

Version is now 0.3.0:1 — this branch rebased onto your v0.3.0:0 transaction-history release, so it stacks on top of it. README, instructions.md, and the dependency description are updated to say 0.20 and 0.21 are supported.

Test plan

  • CI build green.
  • Install on a 0.4.0 server with LND 0.20 — confirm the Auto-Configure task appears, approving it enables onion messages in lnd.conf, and BOLT12 offers can then be created and paid.
  • Install on a server with LND 0.21 — confirm no task appears and BOLT12 offers work with no lnd.conf changes.
  • Upgrade LND 0.20 → 0.21 with BOLT12 Pay installed — confirm the task disappears rather than re-firing, and LND does not crash-loop (feature bit: 39 already set).

Flagging one thing I did not decide for you: your 0.3.0:0 release notes say "compatibility with both LND 0.20.x and LND 0.21.x", which is now accurate again — but let me know if you'd rather the :1 notes word the 0.20 story differently.

@Alex71btc

Copy link
Copy Markdown

Thanks @helix-nine , excellent!

@Alex71btc

Alex71btc commented Jul 12, 2026

Copy link
Copy Markdown

Also release 0.3.0.1 has been merged already and a small follow-up fix PR 0.3.0:2 is pending for bolt 12 pay.

helix-nine and others added 7 commits July 13, 2026 16:52
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5qZh4QiVySBLkV5ya7XSr
…n real address changes

Doctrine v3 (issue start-technologies#3407): dependency addresses go
through a utils.ts bridgeAddress helper chained .const() — the mapped
value is the minimal bridge address, so main never restarts on
dependency updates, and heals with one restart when a dependency is
installed after this service, uninstalled, or changes port. Cross-
package container IPs and .startos dials are gone; static config
defaults become loopback placeholders; tor consumers fold the
allocator-guaranteed 9050 fallback into the map.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PpJxhk25X42WTafMdkUx6t
- no fabricated dependency addresses: absent dependency => absent
  config/env value (optional fields, omitted keys), never a fake
  127.0.0.1 dial default
- dependency-task accept entries match absent-when-default fields
  (prune: 0 or absent both accepted)
- neutral naming: the Bitcoin dependency is 'Bitcoin', not 'Bitcoin
  Core'/'Bitcoin Knots', across prose, release notes, and i18n
- instructions.md keeps no version/migration notes
- remove orphaned i18n entries added by the migration
- normalize the bridgeAddress helper to an explicit early-return and
  prettier-format wave-touched files

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PpJxhk25X42WTafMdkUx6t
Bumps @start9labs/start-sdk ^2.0.1 -> 2.0.3 (dependency and lockfile only).

- 2.0.3 fixes a dependency-gated daemon wedging permanently after its
  dependency's readiness flaps: Daemon.term() unconditionally destroyed the
  daemon's SubContainer, so the next start() threw "already destroyed" and the
  daemon never recovered. Adds a non-destroying Daemon.stop() for
  dependency-driven pauses, and serializes pause/resume transitions.
- 2.0.2 runs s9pk.mk's check-deps before packing, not just before install.

No packaging API changed between 2.0.1 and 2.0.3, so no source changes were
needed. Verified with `npm run check` (tsc --noEmit).

Also pins the dependency exactly rather than with a caret range, matching
the convention used by every other package in both registries.
…head

Re-resolves the git-ref dependencies (bitcoin-core-startos, lnd-startos) to the current head of the
branch each spec points at. These pins predated the start-sdk 2.0.3 bump, so
each dependency dragged a nested @start9labs/start-sdk 2.0.1 into this
package's lockfile. They now resolve to 2.0.3 and dedupe against the
top-level copy, leaving no 2.0.1 anywhere in the tree.

Lockfile only; package.json is unchanged. Verified with `npm run check`.
…gure task

BOLT12 Pay runs fine against LND 0.20 — only the onion-message configuration
step differs — so requiring >=0.21 would lock out operators who upgrade LND
conservatively, for no functional gain.

Restore the dependency floor to >=0.20.1-beta:12 and post LND's hidden
autoconfig task only where it is actually needed: LND advertises onion messages
natively from 0.21 (feature bit 39) and aborts server creation if the pre-0.21
protocol.custom-* overrides are also set, while 0.20 requires them. The installed
version is read with sdk.getServiceManifest(...).const(), so upgrading LND from
0.20 to 0.21 re-runs init and clears the task instead of stranding the user with
a critical task that a 0.21 node can no longer satisfy.

LND 0.21's config spec drops the onion-messages toggle entirely, so the typed
action we import can no longer describe the field; the task is posted through the
raw effects.action.createTask with the same replayId the SDK helper derives.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rtos pins

Bumps @start9labs/start-sdk 2.0.3 -> 2.0.5 (dependency and lockfile only).

2.0.5 fixes ExVer range operations ignoring the downstream revision:
compareVersionRangePoints and adjacentVersionRangePoints compared the upstream
twice, so two points sharing an upstream but differing downstream (1.0.0:3 vs
1.0.0:15) collapsed into one. normalize() then dropped the lower of the two,
which made packed manifests advertise a canMigrateFrom/canMigrateTo range
narrower than the truth for any package whose `other` versions share current's
upstream. No upgrade path actually broke — StartOS resolves migrations through
the version graph rather than this field — but the manifests were wrong.

Also re-resolves the git-ref dependencies (bitcoin-core-startos, lnd-startos) to the current head of the
branch each spec points at, so they carry start-sdk 2.0.5 too and dedupe
against the top-level copy instead of nesting a stale one.

No packaging API changed, so no source changes were needed. Verified with
`npm run check` (tsc --noEmit).
Rebases `next` onto `main` after PR #27 merged, and drops the work that became
redundant.

PR #27 independently did the same upstream submodule bump this branch was carrying
(both landed on 54a4b5f, "Restore NWC initialization after admin page startup
refactor") and released it as 0.3.0:2. So that commit is now a no-op here, and its
release notes would have re-announced, under 0.3.0:3, the NWC fix that 0.3.0:2
already shipped. Dropped it; the submodule is unchanged relative to main.

The release notes now describe what this version actually adds over 0.3.0:2:

- The Auto-Configure task is version-aware. LND's dependency floor is unchanged
  (>=0.20.1-beta:12 on both branches — 0.20 support was never lost), but master
  posts the task unconditionally, including to 0.21 nodes. That is wrong in two
  ways: 0.21 advertises onion messages natively and its config spec drops the
  toggle entirely, so the task is a *critical* item the user cannot satisfy; and
  setting the pre-0.21 protocol.custom-* overrides on 0.21 aborts server creation
  ("feature bit: 39 already set") and crash-loops LND. The task is now posted only
  to pre-0.21 nodes and cleared when LND is upgraded.
- Reactive dependency address resolution, so main no longer restarts on every
  dependency update and heals with one restart when a dependency is installed
  later, removed, or changes port.
- Internal start-sdk 2.0.x updates.

Also keeps this branch's CI fix rather than letting the rebase regress it: master's
workflows point at `start9labs/shared-workflows`, which is retired — the callers
here reference `Start9Labs/start-technologies`.

Verified: lockfile resolves start-sdk 2.0.5 with no nested stale copy and is at a
fixed point; `npm run check` (tsc --noEmit) green.
@Alex71btc

Alex71btc commented Jul 15, 2026

Copy link
Copy Markdown

@helix-nine I just merged Internationalize Lightning Activity history into Alex71btc/lndk-pay main (69d0f9d), the upstream repo.
Before PR #24 is merged, it would be great to update the upstream/ submodule one last time so StartOS ships with the latest UI translations as well.

… history)

Points ./upstream (Alex71btc/lndk-pay) at latest main, bringing in the
internationalized Lightning Activity history UI (ac72629, d40ad07, merged
in 69d0f9d). Clean fast-forward from 54a4b5f; only the frontend
translations change, which the Dockerfile bakes into the image via
`COPY upstream/app/`. Package version stays 0.3.0:3 (this PR is unreleased).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@helix-nine

Copy link
Copy Markdown
Author

@Alex71btc Done — advanced ./upstream (Alex71btc/lndk-pay) from 54a4b5f to your latest main at 69d0f9d in f42c65a, so the internationalized Lightning Activity history UI ships with this release.

  • Clean fast-forward — the only changes are your two translation commits (ac72629 "Add translations for Lightning Activity history", d40ad07 "Internationalize Lightning Activity history"), merged in 69d0f9d. Just app/frontend/admin/index.html.
  • These are baked into the image (the Dockerfile does COPY upstream/app/), so the built .s9pk picks up the new UI translations.
  • Package version stays 0.3.0:3 — this PR is still unreleased, so the submodule refresh just folds into the pending revision rather than needing a new one. Let me know if you'd rather I add a line to the 0.3.0:3 release notes calling out the internationalized activity history.

CI will rebuild against the new pin. Ready for another look whenever you are.

@Alex71btc

Copy link
Copy Markdown

Thanks — perfect!

Yes, please add a short note to the 0.3.0:3 release notes so the user-facing History improvement is visible as well:

“Also adds German and English translations for the Lightning Activity history UI.”

Keeping the package version at 0.3.0:3 makes sense since the PR is still unreleased.

…rtos pins

Bumps @start9labs/start-sdk 2.0.5 -> 2.0.6 (dependency and lockfile only).

2.0.6 fixes s9pk.mk failing under `make` in a git repo with no index yet: it
listed $(GIT_DIR)/index as an unconditional prerequisite, but `git init` creates
no index until the first `git add`, so a freshly scaffolded package aborted with
"No rule to make target '.git/index'" before packing. GIT_DEPS now filters
through $(wildcard ...), so a missing HEAD or index drops out of the prerequisite
list instead of halting the build (s9pk pack already handles a commit-less repo).
Build plumbing only.

Also re-resolves the git-ref dependencies (bitcoin-core-startos, lnd-startos) to the current head of the
branch each spec points at, so they carry start-sdk 2.0.6 too and dedupe
against the top-level copy instead of nesting a stale one.

No packaging API changed, so no source changes were needed. Verified with
`npm run check` (tsc --noEmit).
@helix-nine
helix-nine merged commit a8ba985 into main Jul 23, 2026
3 checks passed
@helix-nine

Copy link
Copy Markdown
Author

Thanks for the review, @MattDHill — this merged and the Tag and Release workflow is cutting 0.3.0:3 now (v0.3.0_3a8ba985).

@Alex71btc, one honest flag: your 07-15 request to add the History note to the 0.3.0:3 release notes — "Also adds German and English translations for the Lightning Activity history UI" — slipped through before the tag was cut, so it's not in the shipped :3 notes. My miss.

The feature itself did ship in :3, though: the upstream submodule advanced 54a4b5f69d0f9d (your internationalized Lightning Activity history), which is baked into the image via COPY upstream/app/. So users on :3 get the translated UI — only the release-notes callout is missing, not the translations.

Since :3 is now released I can't edit its notes retroactively. Your call on how to surface it:

  • Follow-up 0.3.0:4 adding just that line — visible immediately, but it'd re-announce a feature already present in :3.
  • Fold it into the next real release — no notes-only revision, but it waits.

Happy to open the 0.3.0:4 follow-up right now if you'd rather have it visible soon; otherwise I'll roll the note into whatever ships next. Didn't want to spin a new released revision without your sign-off.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants