Skip to content

feat(channel-auth): quorum-gated asset enable/disable lifecycle events#33

Merged
AquiGorka merged 1 commit into
mainfrom
feat/asset-lifecycle
Jun 17, 2026
Merged

feat(channel-auth): quorum-gated asset enable/disable lifecycle events#33
AquiGorka merged 1 commit into
mainfrom
feat/asset-lifecycle

Conversation

@AquiGorka

@AquiGorka AquiGorka commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

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)

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.0release.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.

Add enable_channel/disable_channel on the council channel-auth contract,
quorum-gated via enforce_owner_auth (owner = council quorum), emitting an
event-only ChannelStateChanged{channel, asset, enabled} record. The contract
holds no channel/asset state; the council DB and providers converge on the
event. Re-enable reuses enable_channel (same enabled=true record).

Unit tests: event fields for enable/disable/re-enable, and non-owner rejection.
@AquiGorka
AquiGorka merged commit 061de50 into main Jun 17, 2026
6 of 12 checks passed
@AquiGorka
AquiGorka deleted the feat/asset-lifecycle branch June 17, 2026 16:52
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.)
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.

1 participant