diff --git a/scripts/publication-copy.test.mjs b/scripts/publication-copy.test.mjs new file mode 100644 index 0000000..c802e11 --- /dev/null +++ b/scripts/publication-copy.test.mjs @@ -0,0 +1,41 @@ +// Copy-only regression checks for #232. These are source-contract tests, +// not proof of rendered behavior, independent verification, or live readiness. +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; + +const read = path => readFileSync(new URL(`../${path}`, import.meta.url), 'utf8'); + +for (const path of ['src/components/ShareModal.tsx', 'src/components/publish/PublishModal.tsx']) { + test(`${path}: both publication states explain mutable public contents`, () => { + const source = read(path); + assert.match(source, /The public link shows the current list and can change after publication\./); + assert.match(source, /It does not show or verify a sealed snapshot\./); + assert.doesNotMatch(source, /verify who added each item|verifiable DID|with a verifiable/); + }); +} + +for (const path of ['src/pages/PublicList.tsx', 'src/components/SharedListResource.tsx']) { + test(`${path}: reader labels current data independently of evidence presence`, () => { + const source = read(path); + assert.match(source, /
{ + const source = read('src/components/publish/PublishModal.tsx'); + assert.match(source, /can see the current list contents\. This page does not verify item authorship\./); + assert.doesNotMatch(source, /recorded contributor names|Contributor names will be shown/); +}); + +test('canonical public reader never treats proof presence or a DID as verification', () => { + const source = read('src/components/SharedListResource.tsx'); + assert.doesNotMatch(source, /Cryptographically signed|Verified with/); + assert.match(source, /Supplied proof \(unverified\)/); + assert.match(source, /Declared issuer:/); + assert.match(source, /Identifier \(unverified\):/); + assert.match(source, /These supplied details have not been cryptographically verified by this page\./); +}); diff --git a/src/components/ShareModal.tsx b/src/components/ShareModal.tsx index a1c9ba7..6bc049a 100644 --- a/src/components/ShareModal.tsx +++ b/src/components/ShareModal.tsx @@ -250,7 +250,7 @@ export function ShareModal({ list, onClose }: ShareModalProps) { ) : ( <>

- Publish this list with a verifiable did:webvh identity. + Publish this list with a did:webvh identifier. Anyone with the link can read the list. Publishing does not grant editing access.

@@ -262,7 +262,7 @@ export function ShareModal({ list, onClose }: ShareModalProps) {

What happens when you publish

@@ -290,6 +290,11 @@ export function ShareModal({ list, onClose }: ShareModalProps) { )} +

+ The public link shows the current list and can change after publication. + It does not show or verify a sealed snapshot. +

+

Removing a named grant does not stop public reading while publication is active. To end public access, unpublish the list. Accepted viewers and editors keep their private access.

diff --git a/src/components/SharedListResource.tsx b/src/components/SharedListResource.tsx index d1b0f25..bbefb3f 100644 --- a/src/components/SharedListResource.tsx +++ b/src/components/SharedListResource.tsx @@ -263,6 +263,14 @@ export function SharedListResource() { )}
+
+

Live list · not a sealed snapshot

+

+ This page shows the current list, which can change after publication. + It does not verify a sealed snapshot or who added each item. +

+
+ {/* Plan limit hit when saving to favourites */} {bookmarkPlanLimit && (
@@ -368,15 +376,18 @@ export function SharedListResource() { {/* Provenance */} {resource.credential?.proof && ( -
-
+
+
- + - Cryptographically signed + Supplied proof (unverified)
-
-

Signed by: {resource.credential.issuer}

+

+ These supplied details have not been cryptographically verified by this page. +

+
+

Declared issuer: {resource.credential.issuer}

Date: {new Date(resource.credential.proof.created).toLocaleString()}

Cryptosuite: {resource.credential.proof.cryptosuite}

@@ -390,7 +401,7 @@ export function SharedListResource() { boop - {" "}· Verified with{" "} + {" "}· Identifier (unverified):{" "} did:webvh

diff --git a/src/components/publish/PublishModal.tsx b/src/components/publish/PublishModal.tsx index bc37260..9275be1 100644 --- a/src/components/publish/PublishModal.tsx +++ b/src/components/publish/PublishModal.tsx @@ -3,7 +3,7 @@ * Uses Panel component for slide-up drawer experience. * * Phase 4: Allows list owners to publish their lists publicly. - * Published lists are verifiable and can be viewed by anyone. + * Published lists can be viewed by anyone; this panel does not verify authorship. */ import { useState } from "react"; @@ -308,7 +308,7 @@ export function PublishModal({ list, onClose }: PublishModalProps) { <>

Publishing makes this list publicly viewable. Anyone with the link - can see the list contents and verify who added each item. Editing requires an accepted editor invitation; publishing does not grant editing access. + can see the current list contents. This page does not verify item authorship. Editing requires an accepted editor invitation; publishing does not grant editing access.

@@ -330,7 +330,6 @@ export function PublishModal({ list, onClose }: PublishModalProps) {

Before you publish

  • • All items will be publicly visible
  • -
  • • Contributor names will be shown
  • • The list URL will be shareable
@@ -339,6 +338,11 @@ export function PublishModal({ list, onClose }: PublishModalProps) { )} +

+ The public link shows the current list and can change after publication. + It does not show or verify a sealed snapshot. +

+

Named access is separate from publication. Removing a grant does not stop public reading while publication is active. Unpublishing ends public access; accepted viewers and editors keep their private access.

diff --git a/src/pages/PublicList.tsx b/src/pages/PublicList.tsx index 1fb078a..dd15c40 100644 --- a/src/pages/PublicList.tsx +++ b/src/pages/PublicList.tsx @@ -2,7 +2,7 @@ * Public list view page. * * Phase 4: Displays a published list that anyone can view without authentication. - * Shows items with attribution and verification status. + * Shows current items with recorded attribution and unverified identifier details. */ import { useEffect } from "react"; @@ -103,6 +103,15 @@ export function PublicList() {
+
+

Live list · not a sealed snapshot

+

+ This page shows the current list, which can change after publication. + It does not verify a sealed snapshot or who added each item. + Contributor names are recorded attribution. +

+
+ {/* Items */}
{items.length === 0 ? (