From f3264c8de5f086b80706f9f12779bfb5bbaf173a Mon Sep 17 00:00:00 2001 From: archipelago Date: Tue, 6 Oct 2026 07:56:44 -0400 Subject: [PATCH] Test fail-closed sharing against older backends --- docs/post-1.9.0-progress-20261006.md | 8 ++++++ .../cloud/__tests__/SharePublication.test.ts | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/docs/post-1.9.0-progress-20261006.md b/docs/post-1.9.0-progress-20261006.md index c33ee821..704bb07f 100644 --- a/docs/post-1.9.0-progress-20261006.md +++ b/docs/post-1.9.0-progress-20261006.md @@ -425,3 +425,11 @@ backend result or the archived dashboard build, and are not deployed. The runnin The operator-funded wallets remain untouched in this pass. The private ledger retains the 25-sat inclusive test cap and zero spent. Deployment coordination and the durable payment recovery gates above remain open. + +Qualification follow-up: the atomic endpoint change passed five focused UI tests +and `vue-tsc --noEmit`. The added old-server rejection case also passed (six UI +cases total): no fallback to legacy writes, no success event, and the error stays +visible. A final rerun corrects a missing required prop in that test fixture. +Authenticated read-only checks confirm both dev and Yaya have at least 25 Cashu +sats available. No payment, deployment or release occurred. Backend compilation +for the atomic sharing suite remains in progress; it is not marked passed. diff --git a/neode-ui/src/components/cloud/__tests__/SharePublication.test.ts b/neode-ui/src/components/cloud/__tests__/SharePublication.test.ts index f8c1a491..0d8d1ecf 100644 --- a/neode-ui/src/components/cloud/__tests__/SharePublication.test.ts +++ b/neode-ui/src/components/cloud/__tests__/SharePublication.test.ts @@ -23,3 +23,29 @@ it.each([false, true])('publishes one complete policy for an existing share: %s' expect(writes[0]?.params).toMatchObject(existing ? { id: 'saved-id' } : { filename: 'film.mp4' }) wrapper.unmount() }) + +it('keeps a rejected publication open without falling back to unsafe legacy writes', async () => { + vi.mocked(rpcClient.call).mockImplementation(async ({ method }) => { + if (method === 'content.list-mine') return { items: [] } + if (method === 'content.publish') throw new Error('Method not found') + return {} + }) + const wrapper = mount(ShareModal, { props: { filename: 'film.mp4', filepath: '/film.mp4', isDir: false } }) + await flushPromises() + const vm = (wrapper.vm as any).$.setupState + vm.shared = true + vm.accessType = 'paid' + vm.priceSats = 1 + await vm.save() + await vi.runAllTimersAsync() + expect(vm.errorMsg).toBe('Method not found') + expect(vm.successMsg).toBeNull() + expect(vm.saving).toBe(false) + expect(wrapper.emitted('saved')).toBeUndefined() + const methods = vi.mocked(rpcClient.call).mock.calls.map(([call]) => call.method) + expect(methods.filter(method => method === 'content.publish')).toHaveLength(1) + expect(methods).not.toContain('content.add') + expect(methods).not.toContain('content.set-pricing') + expect(methods).not.toContain('content.set-availability') + wrapper.unmount() +})