feat(channels): on-chain asset lifecycle — watcher is sole status writer#47
Merged
Conversation
The channel-auth ChannelStateChanged event is now the authoritative source of
channel status. Adds a council_channels.status column ('enabled'|'disabled')
plus an optimistic pending_action UX marker, written via migration 0006.
- event-watcher: decode + handle channel_state_changed → setStatusByContractId
(the ONLY path that writes status); clears pending_action on confirmation.
- enable/disable/re-enable endpoints record intent only (pending_action) and
return 202; they never write status ahead of confirmed on-chain state. The
quorum tx is signed client-side. Disable no longer soft-deletes.
- public channel queries expose status so providers converge on disabled
channels (withdraw-only) instead of seeing them disappear.
- tests: event decode, repository status/pending semantics, API pending flow.
This was referenced Jun 15, 2026
AquiGorka
added a commit
to Moonlight-Protocol/soroban-core
that referenced
this pull request
Jun 17, 2026
#33) Part of the multi-asset **asset-lifecycle mechanism** (UC6): a council can enable / disable / re-enable an asset, and every provider converges on the current state. This repo adds the quorum-gated, **event-only** contract surface on channel-auth: - `enable_channel(channel, asset)` / `disable_channel(channel, asset)`, gated by `enforce_owner_auth` (owner = council quorum), mirroring `add_provider`/`remove_provider`. - New event `ChannelStateChanged { channel, asset, enabled }`. The contract holds **no** channel/asset state — the event is the only on-chain artifact. Re-enable reuses `enable_channel`. - Unit tests: event fields for enable/disable/re-enable + non-owner rejection. - Workspace version 0.2.1 → 0.3.0. fmt/clippy/test green; `stellar contract build` exports the new functions. Relates to ClickUp 86c903393. ## Coordinated PRs (review/merge together) - soroban-core: #33 - council-platform: Moonlight-Protocol/council-platform#47 - provider-platform: Moonlight-Protocol/provider-platform#122 - local-dev: Moonlight-Protocol/local-dev#119 ## Release on merge Contains the version bump `Cargo.toml` 0.2.1 → **0.3.0**. On merge to `main`: `auto-tag.yml` → tag **v0.3.0** → `release.yml` builds `channel_auth_contract.wasm` + `privacy_channel.wasm`, publishes the **GitHub Release** (canonical WASM source consumed by the E2E gate), and **dispatches the cross-repo E2E**. Per DEPLOY-STRATEGY.md, order is irrelevant — intermediate E2E fails are expected; the last platform release triggers the passing multi-asset run.
AquiGorka
added a commit
to Moonlight-Protocol/provider-platform
that referenced
this pull request
Jun 17, 2026
#122) Part of the multi-asset **asset-lifecycle mechanism** (UC6). Providers converge on the council's asset enable/disable decisions: - event-watcher decodes/handles `channel_state_changed`; the registry gains a distinct `disabled` state (separate from pending/inactive), keyed by privacy-channel id. - **Withdraw-only gate**: a disabled channel rejects deposits/sends (`CHANNEL_DISABLED`) and allows withdrawals (incl. change). Re-enable resumes full service. - Convergence-by-query on boot + on out-of-retention recovery (cursor reset + council re-query); deterministic unit coverage for query→reconcile and retention detection/recovery. - Dashboard channel summary reports the disabled count. - 99 integration + unit green on deno 2.8.2. Version 0.7.10 → 0.8.0. Note: a rare **pre-existing** WS-timeout flake in `ws-handler_test.ts` (tracked separately, out of scope) can red CI intermittently — re-run if it does. Relates to ClickUp 86c903393. ## Coordinated PRs (review/merge together) - soroban-core: Moonlight-Protocol/soroban-core#33 - council-platform: Moonlight-Protocol/council-platform#47 - provider-platform: #122 - local-dev: Moonlight-Protocol/local-dev#119 ## Release on merge Contains the version bump `deno.json` 0.7.10 → **0.8.0**. On merge to `main`: `auto-tag.yml` → tag **v0.8.0** → `release.yml` builds the **GHCR image `0.8.0`**, dispatches the cross-repo E2E, and **auto-deploys to Fly.io testnet after the E2E gate passes** (blue/green; this change is additive/backward-compatible). Order-independent per DEPLOY-STRATEGY.md.
AquiGorka
added a commit
to Moonlight-Protocol/local-dev
that referenced
this pull request
Jun 17, 2026
Part of the multi-asset **asset-lifecycle mechanism** (UC6) — validation. Extends the multi-asset suite (carried forward from the UC6 validation work) to drive the full lifecycle on-chain against the **real** council watching the **real** chain: - Provider joins the seeded council via the **real** dashboard join API (starts its on-chain watcher); membership activates from the `provider_added` chain event, pulling channel config (with status) from the council. - Lifecycle: council `disable_channel(USDC)` on-chain → council DB tracks the chain → provider converges on the live event → **withdraw-only** (deposit + send rejected, withdraw works, XLM unaffected) → `enable_channel` → full service resumes. - `lib/admin`: enable/disable helpers; compose: `COUNCIL_DATABASE_URL`. Green via `./test.sh multi-asset` (~210s). Boot-sync + out-of-retention are covered by deterministic provider-platform unit tests (per PM decision). Relates to ClickUp 86c903393. ## Coordinated PRs (review/merge together) - soroban-core: Moonlight-Protocol/soroban-core#33 - council-platform: Moonlight-Protocol/council-platform#47 - provider-platform: Moonlight-Protocol/provider-platform#122 - local-dev: #119 ## Release on merge local-dev is **not versioned** — merging does not release. It places the multi-asset **asset-lifecycle** suite on `main` so the cross-repo E2E dispatched by the platform releases runs the new enable/disable → withdraw-only assertions. The dispatched E2E checks out local-dev `main`, so this must be on `main` **before the last platform release dispatches**. (Node pinned via #120, merged.)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the multi-asset asset-lifecycle mechanism (UC6).
council-platform becomes the source of truth + queryable current state, written only from confirmed on-chain events:
council_channels.status(enabled|disabled) +pending_action(optimistic UX marker).channel_state_changedand is the sole authoritative writer of channel status — never written ahead of the chain.pending_action); the quorum tx is signed client-side. Disable no longer soft-deletes.statusso providers converge on disabled channels (withdraw-only) instead of seeing them disappear.Relates to ClickUp 86c903393.
Coordinated PRs (review/merge together)
Release on merge
Contains the version bump
deno.json0.4.24 → 0.5.0. On merge tomain:auto-tag.yml→ tag v0.5.0 →release.ymlbuilds + pushes the GHCR image0.5.0(includes migration 0006council_channels.status) and dispatches the cross-repo E2E. Order-independent per DEPLOY-STRATEGY.md.