diff --git a/docs/proofrun/workflows/README.md b/docs/proofrun/workflows/README.md new file mode 100644 index 0000000..bf84b62 --- /dev/null +++ b/docs/proofrun/workflows/README.md @@ -0,0 +1,17 @@ +# ProofRun V1 workflows + +The YAML files in this directory are executable `proofrun.dev/v1` contracts. +They were migrated from the operator checklists in `../flows`; those source +checklists remain available for audit history during the transition. + +Execution resolves versioned customer and device contracts from the private +`p2ppsr/proofrun-presets` catalog. The migration baseline is ProofRun core +`283f357309a844dde0821dcdc61facbb7f9def64` and catalog +`017c11ec2edbec22371a8e53e7b6511e47ab56b6`. + +Ordinary Chromium/WebKit viewport cases can run on Playwright workers today. +Cases naming `ios-simulator`, `android-emulator`, Metanet Explorer, or +Metanet Client remain unschedulable until a runner advertises the corresponding +real device bridge and capabilities. A workflow never executes the arbitrary +local shell commands from the legacy `preflight.commands`; required-state +statements were converted to V1 oracle assertions. diff --git a/docs/proofrun/workflows/papertrade-admin-review-ledger-payout.v1.proofrun.yaml b/docs/proofrun/workflows/papertrade-admin-review-ledger-payout.v1.proofrun.yaml new file mode 100644 index 0000000..04ec2eb --- /dev/null +++ b/docs/proofrun/workflows/papertrade-admin-review-ledger-payout.v1.proofrun.yaml @@ -0,0 +1,235 @@ +apiVersion: proofrun.dev/v1 +kind: Workflow +metadata: + id: papertrade-admin-review-ledger-payout + name: PaperTrade admin review, ledger, and payout lifecycle + version: 1.0.0 + description: An authorized PaperTrade operator validating publication review, reader purchase accounting, author balance, and payout handling. + labels: + migration: proofrunVersion-1 + repository: p2ppsr/PaperTrade + category: admin +target: + type: web + url: https://papertrade.metanet.app + environment: production +matrix: + maxCases: 4 + exclude: + - {} + include: + - agent: openai-computer + profile: customer.domain-expert@1.0.0 + accessibility: standard + device: device.chromium-desktop@1.0.0 + legacyDesktopBrowser: chrome + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.domain-expert@1.0.0 + accessibility: standard + device: device.android-emulator@1.0.0 + legacyMobileSimulator: android-emulator + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.domain-expert@1.0.0 + accessibility: standard + device: p2ppsr.metanet-client-macos@1.0.0 + legacyDesktopWallet: localhost-json-api-wallet-bridge + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.domain-expert@1.0.0 + accessibility: standard + device: p2ppsr.metanet-client-macos@1.0.0 + legacyDesktopWallet: bsv-browser + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet +capabilities: + - browser + - wallet.profile-restore +journeys: + - id: admin + goal: PaperTrade admin review, ledger, and payout lifecycle + role: An authorized PaperTrade operator validating publication review, reader purchase accounting, author balance, and payout handling. + maxActions: 36 + maxSeconds: 180 + steps: + - id: authenticate-admin + instruction: Open /admin and approve the wallet auth/access request. + expected: "UI: Admin workspace loads only for the approved admin identity. UI: Admin tabs for Publications, Settings/Admins, and Payouts are visible and usable. Wallet: Auth succeeds without payment. Telemetry: page.view, wallet.prompt_shown, and wallet.action_succeeded are emitted as applicable." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: review-publication + instruction: Review the ProofRun author publication and publish, reject, unpublish, or return to review according to the planned branch. + expected: "UI: The admin can inspect metadata and rendered preview before changing status. UI: Status change produces clear confirmation. Domain: Publication status changes exactly once to the selected target state. Domain: Public catalog visibility matches published/unpublished status. Telemetry: One of admin.publication_submitted, admin.publication_published, admin.publication_rejected, admin.publication_unpublished, or admin.publication_returned_to_review is emitted." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: generate-author-balance + instruction: If no qualifying balance exists, run a low-value paid-page purchase against the published ProofRun publication or selected test publication. + expected: "UI: The reader receives the paid page after approval. Domain: Author balance increases by the expected net amount and platform commission is represented correctly. Telemetry: reader.paid_page_unlocked is emitted and can be correlated to ledger state." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: inspect-ledger-and-create-payout + instruction: Open the Payouts section, inspect author balances, and create or prepare the payout according to the spend cap and server-wallet readiness. + expected: "UI: Author balances are understandable and selectable. UI: Payout creation has a clear result: created, pending wallet receipt, succeeded, or actionable failure. Domain: A payout record is created only when amount, author, and server wallet balance are valid. Domain: Failed payout attempts record a safe failure reason without corrupting balance state. Telemetry: payout.created, payout.succeeded, or payout.failed is emitted according to result." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: author-receives-or-retries-payout + instruction: Open /author and complete wallet receipt for a pending payout, or verify actionable retry/support state if receipt cannot be completed. + expected: "UI: Author payout state is clear and does not imply funds received before wallet receipt. UI: Retry wallet receipt and payout support are visible when needed. Domain: Payout status moves to succeeded or remains pending/failed with correct reason. Wallet: If internalization succeeds, the wallet confirms receipt. Telemetry: payout.succeeded or payout.failed is emitted according to outcome." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: cleanup-test-state + instruction: Apply the documented cleanup plan for ProofRun publication/admin changes where appropriate. + expected: "Domain: Cleanup changes are recorded in run evidence. Domain: Financial audit records are not deleted or obscured. Telemetry: Cleanup status changes emit the appropriate admin event." + evidence: + - screenshot + - trace + - log + onFailure: stop +assertions: + - id: uiappearance-1 + type: visual + severity: fail + statement: Admin, payout, author, and reader states remain usable on required desktop and selected wallet/mobile substrate. + - id: uiappearance-2 + type: visual + severity: fail + statement: Tabs, forms, balance rows, payout actions, and confirmations do not overlap or hide critical data. + - id: audienceintuition-1 + type: agent + severity: fail + statement: An operator can understand publication status, author balances, payout readiness, and failure reasons without reading source code. + - id: audienceintuition-2 + type: agent + severity: fail + statement: Authors can understand whether a payout is received, pending wallet receipt, or failed. + - id: customertrust-1 + type: security + severity: fail + statement: Reader payment, author balance, platform commission, and payout state are internally consistent. + - id: customertrust-2 + type: security + severity: fail + statement: No UI claims funds or publication status that the backend has not recorded. + - id: customertrust-3 + type: security + severity: fail + statement: Failures explain whether the issue is server wallet funding, author wallet receipt, invalid amount, or permissions. + - id: flowsuccess-1 + type: oracle + severity: fail + statement: Admin auth is enforced. + - id: flowsuccess-2 + type: oracle + severity: fail + statement: Publication review action changes state exactly as intended. + - id: flowsuccess-3 + type: oracle + severity: fail + statement: A reader purchase produces the expected ledger/balance effect. + - id: flowsuccess-4 + type: oracle + severity: fail + statement: Payout lifecycle reaches succeeded or a correct pending/failed state with no balance corruption. + - id: telemetryobservability-1 + type: oracle + severity: fail + statement: Admin publication events, paid-page conversion, and payout lifecycle events are queryable with source papertrade. + - id: telemetryobservability-2 + type: oracle + severity: fail + statement: Logs and telemetry have no private keys, seed phrases, raw transactions, JWTs, cookies, raw signatures, or wallet storage secrets. + - id: reliabilityrepeatability-1 + type: oracle + severity: fail + statement: The flow can be rerun with a new ProofRun publication/run id. + - id: reliabilityrepeatability-2 + type: oracle + severity: fail + statement: Cleanup and audit boundaries are documented so repeated runs do not pollute production catalog. + - id: performance-1 + type: performance + severity: fail + statement: Admin workspace auth to ready <= 10s. + - id: performance-2 + type: performance + severity: fail + statement: Publication status action confirmation <= 15s. + - id: performance-3 + type: performance + severity: fail + statement: Payout creation result <= 30s. + - id: performance-4 + type: performance + severity: fail + statement: Author payout receipt or actionable failure <= 30s. + - id: required-state-1 + type: oracle + severity: fail + statement: An approved admin wallet identity can access /admin. + tags: + - migrated-preflight + - id: required-state-2 + type: oracle + severity: fail + statement: An approved author/test publication exists or the author submission ProofRun is run first. + tags: + - migrated-preflight + - id: required-state-3 + type: oracle + severity: fail + statement: An approved reader wallet has enough funds for one low-value page purchase. + tags: + - migrated-preflight + - id: required-state-4 + type: oracle + severity: fail + statement: PaperTrade server wallet has enough spendable balance for any payout branch being executed, or payout creation is expected to warn/fail with clear operator guidance. + tags: + - migrated-preflight + - id: required-state-5 + type: oracle + severity: fail + statement: The exact cleanup plan is documented before making admin changes. + tags: + - migrated-preflight +policy: + unsafeContent: stop + highImpactActions: require-approval + allowedHosts: + - papertrade.metanet.app + spendLimit: 250 + warnExitCode: 0 +remediation: + mode: manual + allowed: true + proposalOnly: true + requiredApprovers: 1 +uses: [] diff --git a/docs/proofrun/workflows/papertrade-author-submission-preview.v1.proofrun.yaml b/docs/proofrun/workflows/papertrade-author-submission-preview.v1.proofrun.yaml new file mode 100644 index 0000000..05bac36 --- /dev/null +++ b/docs/proofrun/workflows/papertrade-author-submission-preview.v1.proofrun.yaml @@ -0,0 +1,195 @@ +apiVersion: proofrun.dev/v1 +kind: Workflow +metadata: + id: papertrade-author-submission-preview + name: PaperTrade author submission and preview + version: 1.0.0 + description: An author who wants to publish writing, preview rendered pages, and eventually earn from reader purchases. + labels: + migration: proofrunVersion-1 + repository: p2ppsr/PaperTrade + category: publish +target: + type: web + url: https://papertrade.metanet.app + environment: production +matrix: + maxCases: 3 + exclude: + - {} + include: + - agent: openai-computer + profile: customer.domain-expert@1.0.0 + accessibility: standard + device: device.chromium-desktop@1.0.0 + legacyDesktopBrowser: chrome + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.domain-expert@1.0.0 + accessibility: standard + device: p2ppsr.metanet-client-macos@1.0.0 + legacyDesktopWallet: localhost-json-api-wallet-bridge + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.domain-expert@1.0.0 + accessibility: standard + device: p2ppsr.metanet-client-macos@1.0.0 + legacyDesktopWallet: bsv-browser + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet +capabilities: + - browser + - wallet.profile-restore +journeys: + - id: publish + goal: PaperTrade author submission and preview + role: An author who wants to publish writing, preview rendered pages, and eventually earn from reader purchases. + maxActions: 30 + maxSeconds: 120 + steps: + - id: open-author-workspace + instruction: Open /author with the approved author wallet substrate. + expected: "UI: The Author workspace explains publishing status, balance, publications, and upload controls. UI: If wallet auth is needed, the app explains why before requesting approval. Telemetry: page.view is emitted for /author." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: authenticate-author + instruction: Approve the wallet auth/access request required to load the author workspace. + expected: "UI: The workspace loads without raw identity keys as the main reader-facing language. UI: The author can tell which account is active. Wallet: Auth succeeds without payment. Telemetry: wallet.prompt_shown and wallet.action_succeeded are emitted if auth is required." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: create-publication + instruction: Enter ProofRun title/description metadata and upload the public-safe multi-page fixture. + expected: "UI: The upload process gives progress or clear processing state. UI: The author sees validation errors for unsupported or too-short files. UI: Successful processing shows page count and preview/read action. Domain: The server creates a publication associated with the author identity. Domain: Rendered pages exist for preview. Telemetry: author.publication_submitted or author.publication_published is emitted according to current mode." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: preview-rendered-pages + instruction: Open /author/read//1 and at least one additional rendered preview page. + expected: "UI: Preview pages render as readable images. UI: Back to author action is visible. Domain: Preview access works for the author before public reader access." + evidence: + - screenshot + - trace + - metric + onFailure: stop + - id: verify-publication-state + instruction: Inspect UI, API if available, telemetry, and logs for the new publication. + expected: "Domain: Publication status matches current mode: submitted/review if review is required, published if direct publishing is enabled. Domain: No server log errors or secret-shaped values appear. Telemetry: Author publication event is queryable with safe publication context." + evidence: + - screenshot + - trace + - log + onFailure: stop +assertions: + - id: uiappearance-1 + type: visual + severity: fail + statement: Author workspace, upload form, progress state, publication list, and preview pages fit desktop and wallet browser layouts. + - id: uiappearance-2 + type: visual + severity: fail + statement: File processing state does not look frozen during conversion. + - id: audienceintuition-1 + type: agent + severity: fail + statement: An author can understand what to upload, what happens next, and whether the work is live or awaiting review. + - id: audienceintuition-2 + type: agent + severity: fail + statement: Wallet auth language is understandable and separate from payment language. + - id: customertrust-1 + type: security + severity: fail + statement: The author receives clear confirmation after upload/submission. + - id: customertrust-2 + type: security + severity: fail + statement: The app does not imply earnings or publication before the server state supports it. + - id: flowsuccess-1 + type: oracle + severity: fail + statement: The submitted publication is associated with the author identity and has rendered preview pages. + - id: flowsuccess-2 + type: oracle + severity: fail + statement: Publication status, preview access, and telemetry agree. + - id: telemetryobservability-1 + type: oracle + severity: fail + statement: author.publication_submitted or author.publication_published is visible with source papertrade and safe context. + - id: telemetryobservability-2 + type: oracle + severity: fail + statement: Upload/conversion failures are visible in UI and logs without secret leakage. + - id: reliabilityrepeatability-1 + type: oracle + severity: fail + statement: The same public-safe fixture can be reused with a unique run id. + - id: reliabilityrepeatability-2 + type: oracle + severity: fail + statement: Cleanup/unpublish path is documented if production state remains. + - id: performance-1 + type: performance + severity: fail + statement: Author workspace first meaningful content <= 3s. + - id: performance-2 + type: performance + severity: fail + statement: Wallet auth approval to workspace <= 10s. + - id: performance-3 + type: performance + severity: fail + statement: Fixture processing completes <= 90s or is marked warn with server timing evidence. + - id: required-state-1 + type: oracle + severity: fail + statement: The author wallet is available and approved for production test publication activity. + tags: + - migrated-preflight + - id: required-state-2 + type: oracle + severity: fail + statement: The fixture file has at least 5 pages after conversion and contains no sensitive text. + tags: + - migrated-preflight + - id: required-state-3 + type: oracle + severity: fail + statement: The operator knows whether the current mode is private_publish or public_submissions. + tags: + - migrated-preflight + - id: required-state-4 + type: oracle + severity: fail + statement: Cleanup responsibility is explicit before submission. + tags: + - migrated-preflight +policy: + unsafeContent: stop + highImpactActions: require-approval + allowedHosts: + - papertrade.metanet.app + spendLimit: 0 + warnExitCode: 0 +remediation: + mode: manual + allowed: true + proposalOnly: true + requiredApprovers: 1 +uses: [] diff --git a/docs/proofrun/workflows/papertrade-feedback-usercom-signals.v1.proofrun.yaml b/docs/proofrun/workflows/papertrade-feedback-usercom-signals.v1.proofrun.yaml new file mode 100644 index 0000000..f66c5ea --- /dev/null +++ b/docs/proofrun/workflows/papertrade-feedback-usercom-signals.v1.proofrun.yaml @@ -0,0 +1,187 @@ +apiVersion: proofrun.dev/v1 +kind: Workflow +metadata: + id: papertrade-feedback-usercom-signals + name: PaperTrade feedback and UserCom signal capture + version: 1.0.0 + description: A reader, author, or evaluator who needs to send feedback or support context from a real PaperTrade surface. + labels: + migration: proofrunVersion-1 + repository: p2ppsr/PaperTrade + category: feedback +target: + type: web + url: https://papertrade.metanet.app + environment: production +matrix: + maxCases: 5 + exclude: + - {} + include: + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.chromium-desktop@1.0.0 + legacyDesktopBrowser: chrome + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.webkit-desktop@1.0.0 + legacyDesktopBrowser: safari + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.webkit-mobile@1.0.0 + legacyMobileBrowser: ios-safari + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.chromium-mobile@1.0.0 + legacyMobileBrowser: android-chrome + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.android-emulator@1.0.0 + legacyMobileSimulator: android-emulator + legacyNetworks: mainnet +capabilities: + - browser +journeys: + - id: feedback + goal: PaperTrade feedback and UserCom signal capture + role: A reader, author, or evaluator who needs to send feedback or support context from a real PaperTrade surface. + maxActions: 24 + maxSeconds: 90 + steps: + - id: open-feedback-from-newsstand + instruction: Open the newsstand and open the feedback UI from the primary feedback affordance. + expected: "UI: Feedback is discoverable without knowing internal routes. UI: The modal or panel is visually stable on desktop and mobile. UI: The user can close it without losing page context. Telemetry: feedback.opened is emitted with surface newsstand or equivalent context." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: submit-valid-feedback + instruction: Submit a public-safe ProofRun feedback message with the unique run id. + expected: "UI: The submit button shows immediate progress or disables safely. UI: A clear success confirmation appears. UI: The form does not duplicate-submit on repeated clicks. Domain: The UserCom feedback record contains source papertrade, surface, URL/path, tags, and sanitized context. Telemetry: feedback.submitted is emitted and UserCom /submit returns success." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: submit-invalid-feedback + instruction: Attempt an invalid submission, such as empty feedback or invalid email, without sending sensitive data. + expected: "UI: The user gets actionable validation feedback. UI: The failure does not clear useful entered data unexpectedly. Telemetry: feedback.failed is emitted only if the app attempts and receives a failure; client-only validation may record no backend submission." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: feedback-from-contextual-surfaces + instruction: Open feedback from Help and from a reader or wallet-help/failure context when available. + expected: "UI: Feedback remains discoverable when the user is confused or blocked. UI: Surface-specific context is attached without exposing private wallet material. Telemetry: feedback.opened and feedback.submitted include useful surface tags such as help, reader, or author-payout." + evidence: + - screenshot + - trace + - log + onFailure: stop +assertions: + - id: uiappearance-1 + type: visual + severity: fail + statement: Feedback UI fits desktop and mobile without clipped text, hidden fields, or inaccessible close/submit buttons. + - id: uiappearance-2 + type: visual + severity: fail + statement: Success and failure states are visually distinct. + - id: audienceintuition-1 + type: agent + severity: fail + statement: A user can find feedback from likely confusion points. + - id: audienceintuition-2 + type: agent + severity: fail + statement: Field labels and validation messages are plain language. + - id: customertrust-1 + type: security + severity: fail + statement: The app confirms receipt and does not silently swallow feedback. + - id: customertrust-2 + type: security + severity: fail + statement: The user is not asked for wallet approval to send ordinary feedback. + - id: flowsuccess-1 + type: oracle + severity: fail + statement: A valid feedback submission reaches UserCom and is queryable by run id. + - id: flowsuccess-2 + type: oracle + severity: fail + statement: Invalid submission does not create a misleading success state. + - id: telemetryobservability-1 + type: oracle + severity: fail + statement: feedback.opened, feedback.submitted, and feedback.failed where applicable are visible with source papertrade. + - id: telemetryobservability-2 + type: oracle + severity: fail + statement: Context includes route, surface, release/session context, and no secret-shaped values. + - id: reliabilityrepeatability-1 + type: oracle + severity: fail + statement: The valid submission can be repeated with a unique run id. + - id: reliabilityrepeatability-2 + type: oracle + severity: fail + statement: The form prevents accidental duplicate submissions in a single attempt. + - id: performance-1 + type: performance + severity: fail + statement: Feedback UI opens <= 2s. + - id: performance-2 + type: performance + severity: fail + statement: Submission confirmation appears <= 5s. + - id: performance-3 + type: performance + severity: fail + statement: UserCom visibility <= 60s. + - id: required-state-1 + type: oracle + severity: fail + statement: The operator has a public-safe ProofRun feedback name, email, and message. + tags: + - migrated-preflight + - id: required-state-2 + type: oracle + severity: fail + statement: The feedback message includes a unique run id for UserCom correlation. + tags: + - migrated-preflight + - id: required-state-3 + type: oracle + severity: fail + statement: The operator has a UserCom query path to confirm feedback.submitted and adjacent page.view or feedback.opened events. + tags: + - migrated-preflight +policy: + unsafeContent: stop + highImpactActions: require-approval + allowedHosts: + - papertrade.metanet.app + - usercom.babbage.systems + spendLimit: 0 + warnExitCode: 0 +remediation: + mode: manual + allowed: true + proposalOnly: true + requiredApprovers: 1 +uses: [] diff --git a/docs/proofrun/workflows/papertrade-reader-free-first-page.v1.proofrun.yaml b/docs/proofrun/workflows/papertrade-reader-free-first-page.v1.proofrun.yaml new file mode 100644 index 0000000..7c6574b --- /dev/null +++ b/docs/proofrun/workflows/papertrade-reader-free-first-page.v1.proofrun.yaml @@ -0,0 +1,201 @@ +apiVersion: proofrun.dev/v1 +kind: Workflow +metadata: + id: papertrade-reader-free-first-page + name: PaperTrade reader discovery to first free page + version: 1.0.0 + description: A new reader who is curious about PaperTrade but may not yet understand BSV, wallets, or pay-per-page publishing. + labels: + migration: proofrunVersion-1 + repository: p2ppsr/PaperTrade + category: discover +target: + type: web + url: https://papertrade.metanet.app + environment: production +matrix: + maxCases: 6 + exclude: + - {} + include: + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.chromium-desktop@1.0.0 + legacyDesktopBrowser: chrome + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.webkit-desktop@1.0.0 + legacyDesktopBrowser: safari + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.webkit-mobile@1.0.0 + legacyMobileBrowser: ios-safari + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.chromium-mobile@1.0.0 + legacyMobileBrowser: android-chrome + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.ios-simulator@1.0.0 + legacyMobileSimulator: ios-simulator + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.android-emulator@1.0.0 + legacyMobileSimulator: android-emulator + legacyNetworks: mainnet +capabilities: + - browser +journeys: + - id: discover + goal: PaperTrade reader discovery to first free page + role: A new reader who is curious about PaperTrade but may not yet understand BSV, wallets, or pay-per-page publishing. + maxActions: 24 + maxSeconds: 90 + steps: + - id: open-newsstand + instruction: Open https://papertrade.metanet.app/ in a clean browser context. + expected: "UI: The page title or H1 clearly identifies PaperTrade. UI: The first viewport explains the reading value before wallet mechanics. UI: Navigation includes Newsstand, Help, Author, and Admin without crowding or clipping. UI: The publication grid renders real works, not empty demo placeholders. Telemetry: page.view is emitted with source papertrade and surface newsstand or equivalent route context. Telemetry: newsstand.loaded is emitted after publications render." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: inspect-catalog + instruction: Scan the first screen and at least the first three publication cards. + expected: "UI: Each visible card has a readable title, human author name, short description or metadata, price/page context, page count, and a visible action to read. UI: Cards are tappable/clickable without text overlap at desktop and mobile widths. UI: Search or browse controls do not obscure content or resize the layout unexpectedly. Domain: Rendered publication cards agree with /api/publications for title, id, author, page count, and published status." + evidence: + - screenshot + - trace + onFailure: stop + - id: open-publication-detail + instruction: Open the detail page for the first catalog publication. + expected: "UI: The detail page makes the work, author, page count, and start-reading action obvious. UI: The user can understand that page 1 is free before any paid page is requested. Telemetry: publication.view is emitted with publicationId and safe route context." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: read-page-one-free + instruction: Open page 1 from the publication detail page. + expected: "UI: Page 1 renders as a readable page image. UI: The reader has obvious navigation to continue, return, or get help. UI: No wallet setup prompt appears before page 1 content. Domain: Direct HTTP for /api/publications//pages/1 returns a PNG response with X-PaperTrade-Page-Access: free. Telemetry: reader.first_page_loaded is emitted with publicationId and pageNumber 1." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop +assertions: + - id: uiappearance-1 + type: visual + severity: fail + statement: Desktop 1440x900, tablet 768x1024, and mobile 390x844 viewports have no horizontal overflow, overlapping text, hidden primary actions, or clipped navigation. + - id: uiappearance-2 + type: visual + severity: fail + statement: Publication cards, detail hero, and reader page image use stable dimensions and do not shift after load. + - id: uiappearance-3 + type: visual + severity: fail + statement: Loading and empty states are coherent if network throttling is used. + - id: audienceintuition-1 + type: agent + severity: fail + statement: A non-technical reader can tell what PaperTrade is, what to click first, and that page 1 is free. + - id: audienceintuition-2 + type: agent + severity: fail + statement: Wallet or BSV terminology is not required to understand the first action. + - id: customertrust-1 + type: security + severity: fail + statement: The app does not ask for wallet approval before delivering the promised free page. + - id: customertrust-2 + type: security + severity: fail + statement: Pricing and page-by-page continuation are visible before any paid action. + - id: flowsuccess-1 + type: oracle + severity: fail + statement: Homepage, catalog API, publication detail, and page 1 all agree on the selected publication. + - id: flowsuccess-2 + type: oracle + severity: fail + statement: Page 1 can be loaded from click navigation and by direct deep link. + - id: telemetryobservability-1 + type: oracle + severity: fail + statement: page.view, newsstand.loaded, publication.view, and reader.first_page_loaded are queryable in UserCom or the configured signal sink. + - id: telemetryobservability-2 + type: oracle + severity: fail + statement: Events include source papertrade, safe route context, release context when available, and no private wallet material. + - id: reliabilityrepeatability-1 + type: oracle + severity: fail + statement: The flow passes from a clean browser context and after reload/back/forward. + - id: reliabilityrepeatability-2 + type: oracle + severity: fail + statement: Running the flow twice creates no duplicate domain state because it is read-only. + - id: performance-1 + type: performance + severity: fail + statement: Homepage first meaningful content <= 2s on normal network. + - id: performance-2 + type: performance + severity: fail + statement: Publication detail first meaningful content <= 2s on normal network. + - id: performance-3 + type: performance + severity: fail + statement: Page 1 image visible <= 3s on normal network. + - id: required-state-1 + type: oracle + severity: fail + statement: Production health returns ok:true. + tags: + - migrated-preflight + - id: required-state-2 + type: oracle + severity: fail + statement: The public catalog returns at least one published publication. + tags: + - migrated-preflight + - id: required-state-3 + type: oracle + severity: fail + statement: The first publication has a stable id, title, authorName, pageCount, and cover or fallback cover state. + tags: + - migrated-preflight + - id: required-state-4 + type: oracle + severity: fail + statement: No wallet or paid action is required for this flow. + tags: + - migrated-preflight +policy: + unsafeContent: stop + highImpactActions: deny + allowedHosts: + - papertrade.metanet.app + spendLimit: 0 + warnExitCode: 0 +remediation: + mode: manual + allowed: true + proposalOnly: true + requiredApprovers: 1 +uses: [] diff --git a/docs/proofrun/workflows/papertrade-reader-paid-page-purchase.v1.proofrun.yaml b/docs/proofrun/workflows/papertrade-reader-paid-page-purchase.v1.proofrun.yaml new file mode 100644 index 0000000..07a1b0f --- /dev/null +++ b/docs/proofrun/workflows/papertrade-reader-paid-page-purchase.v1.proofrun.yaml @@ -0,0 +1,218 @@ +apiVersion: proofrun.dev/v1 +kind: Workflow +metadata: + id: papertrade-reader-paid-page-purchase + name: PaperTrade reader paid page purchase + version: 1.0.0 + description: A reader with a funded BRC100-compatible wallet who wants to continue reading after the free first page. + labels: + migration: proofrunVersion-1 + repository: p2ppsr/PaperTrade + category: pay +target: + type: web + url: https://papertrade.metanet.app + environment: production +matrix: + maxCases: 4 + exclude: + - {} + include: + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.chromium-desktop@1.0.0 + legacyDesktopBrowser: chrome + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.android-emulator@1.0.0 + legacyMobileSimulator: android-emulator + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: p2ppsr.metanet-client-macos@1.0.0 + legacyDesktopWallet: localhost-json-api-wallet-bridge + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: p2ppsr.metanet-client-macos@1.0.0 + legacyDesktopWallet: bsv-browser + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet +capabilities: + - browser + - wallet.profile-restore +journeys: + - id: pay + goal: PaperTrade reader paid page purchase + role: A reader with a funded BRC100-compatible wallet who wants to continue reading after the free first page. + maxActions: 30 + maxSeconds: 90 + steps: + - id: open-free-page + instruction: Open a selected publication, read page 1, and click or navigate to page 2. + expected: "UI: The free page is visible before payment. UI: The continuation action makes it clear that the next page is paid. Telemetry: reader.first_page_loaded is emitted before paid-page events." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: start-paid-unlock + instruction: Start the page 2 unlock from the reader UI. + expected: "UI: The app shows immediate progress and does not appear frozen. UI: The user sees language that explains this is a wallet/payment request for unlocking the page. Telemetry: reader.paid_page_access_started is emitted with publicationId and pageNumber 2 before the access/payment request completes. Telemetry: wallet.prompt_shown is emitted when the wallet prompt is expected or displayed." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: approve-wallet-payment + instruction: Approve the wallet request for the paid page within the configured spend cap. + expected: "UI: The wallet prompt shows a comprehensible action and amount before approval. UI: The app remains responsive while approval is pending. Wallet: The wallet returns success for the requested BRC100/payment action. Telemetry: wallet.action_succeeded is emitted after approval." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: verify-paid-page + instruction: Wait for PaperTrade to render page 2 after approval. + expected: "UI: Page 2 image renders and the app gives clear success state without stale wallet-help copy. UI: Reader navigation still works after the paid page loads. Domain: The server records or recognizes an entitlement/payment for the selected reader, publication, and page. Domain: The author ledger and platform commission state are updated when applicable. Telemetry: reader.paid_page_unlocked is emitted from the client or server with safe context." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: verify-production-logs + instruction: Inspect logs and telemetry for the run window. + expected: "Telemetry: The paid conversion sequence is queryable: page.view, reader.first_page_loaded, reader.paid_page_access_started, wallet.prompt_shown, wallet.action_succeeded, reader.paid_page_unlocked." + evidence: + - screenshot + - trace + - log + onFailure: stop +assertions: + - id: uiappearance-1 + type: visual + severity: fail + statement: The paid-page path is usable at desktop and in the selected wallet/browser substrate. + - id: uiappearance-2 + type: visual + severity: fail + statement: Progress, wallet, success, and reader states do not overlap or hide controls. + - id: audienceintuition-1 + type: agent + severity: fail + statement: The reader can tell why the wallet opened and what page is being unlocked. + - id: audienceintuition-2 + type: agent + severity: fail + statement: The app does not expose raw transaction internals as the primary explanation. + - id: customertrust-1 + type: security + severity: fail + statement: The amount and consequence are clear before approval. + - id: customertrust-2 + type: security + severity: fail + statement: The UI never suggests duplicate charge risk while waiting. + - id: customertrust-3 + type: security + severity: fail + statement: After success, the reader can tell the paid page is available. + - id: flowsuccess-1 + type: oracle + severity: fail + statement: Wallet approval, PaperTrade entitlement/payment state, page image rendering, and ledger impact agree. + - id: flowsuccess-2 + type: oracle + severity: fail + statement: The selected page is not unlocked without payment unless it was already owned by the test identity. + - id: telemetryobservability-1 + type: oracle + severity: fail + statement: Conversion and wallet events are queryable in UserCom or the configured sink. + - id: telemetryobservability-2 + type: oracle + severity: fail + statement: Telemetry distinguishes start, prompt, success, and failure states. + - id: telemetryobservability-3 + type: oracle + severity: fail + statement: Telemetry contains no private keys, signatures, BEEF payloads, cookies, JWTs, or raw transactions. + - id: reliabilityrepeatability-1 + type: oracle + severity: fail + statement: A fresh selected page or fresh reader identity can repeat the run. + - id: reliabilityrepeatability-2 + type: oracle + severity: fail + statement: The run record captures enough identity-safe detail to rerun without guessing. + - id: performance-1 + type: performance + severity: fail + statement: Wallet prompt shown <= 5s. + - id: performance-2 + type: performance + severity: fail + statement: Approval to page confirmation <= 10s. + - id: performance-3 + type: performance + severity: fail + statement: Full free-page-to-paid-page flow <= 45s unless the run record justifies slower wallet substrate behavior. + - id: required-state-1 + type: oracle + severity: fail + statement: Production health returns ok:true and setupComplete:true. + tags: + - migrated-preflight + - id: required-state-2 + type: oracle + severity: fail + statement: The selected publication has pageCount >= 2 and page 1 can be opened free. + tags: + - migrated-preflight + - id: required-state-3 + type: oracle + severity: fail + statement: Current pricePerPageSats is known and the run spend cap is greater than or equal to the page price plus fees. + tags: + - migrated-preflight + - id: required-state-4 + type: oracle + severity: fail + statement: The selected reader wallet is authenticated, funded, and approved for a real mainnet low-value spend. + tags: + - migrated-preflight + - id: required-state-5 + type: oracle + severity: fail + statement: The operator has a UserCom query path for source=papertrade. + tags: + - migrated-preflight +policy: + unsafeContent: stop + highImpactActions: require-approval + allowedHosts: + - papertrade.metanet.app + spendLimit: 100 + warnExitCode: 0 +remediation: + mode: manual + allowed: true + proposalOnly: true + requiredApprovers: 1 +uses: [] diff --git a/docs/proofrun/workflows/papertrade-reader-paid-page-reread-no-second-charge.v1.proofrun.yaml b/docs/proofrun/workflows/papertrade-reader-paid-page-reread-no-second-charge.v1.proofrun.yaml new file mode 100644 index 0000000..af61615 --- /dev/null +++ b/docs/proofrun/workflows/papertrade-reader-paid-page-reread-no-second-charge.v1.proofrun.yaml @@ -0,0 +1,190 @@ +apiVersion: proofrun.dev/v1 +kind: Workflow +metadata: + id: papertrade-reader-paid-page-reread-no-second-charge + name: PaperTrade paid page reread and no second charge + version: 1.0.0 + description: A returning reader who already paid for a page and expects access to persist without being charged again. + labels: + migration: proofrunVersion-1 + repository: p2ppsr/PaperTrade + category: redeem +target: + type: web + url: https://papertrade.metanet.app + environment: production +matrix: + maxCases: 4 + exclude: + - {} + include: + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.chromium-desktop@1.0.0 + legacyDesktopBrowser: chrome + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.android-emulator@1.0.0 + legacyMobileSimulator: android-emulator + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: p2ppsr.metanet-client-macos@1.0.0 + legacyDesktopWallet: localhost-json-api-wallet-bridge + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: p2ppsr.metanet-client-macos@1.0.0 + legacyDesktopWallet: bsv-browser + legacyMobileWallets: metanet-explorer-android + legacyServerWallets: papertrade-server-wallet + legacyNetworks: mainnet +capabilities: + - browser + - wallet.profile-restore +journeys: + - id: redeem + goal: PaperTrade paid page reread and no second charge + role: A returning reader who already paid for a page and expects access to persist without being charged again. + maxActions: 24 + maxSeconds: 90 + steps: + - id: open-owned-page-directly + instruction: Open the deep link for the already-owned paid page, such as /read//2, in the same wallet/browser substrate. + expected: "UI: The app loads the owned page or asks only for identity/auth needed to prove ownership. UI: The app does not present wording that suggests a new charge is required. Telemetry: page.view is emitted for the deep link." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: approve-auth-if-needed + instruction: Approve any identity/auth wallet request required for ownership lookup, but do not approve any new payment. + expected: "UI: The wallet request wording is distinguishable from a payment request. UI: The app explains that it is checking access or loading the owned page. Wallet: No spend or payment request is made. Wallet: If a prompt appears, it is an auth/access request consistent with rereading owned content. Telemetry: reader.paid_page_access_started may appear as a neutral access-check event. Telemetry: wallet.prompt_shown and wallet.action_succeeded may appear, but no reader.paid_page_unlock_started should be emitted." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: verify-owned-page-renders + instruction: Wait for the paid page to render, then reload the page. + expected: "UI: The page image renders after direct open and after reload. UI: No stale wallet-help, timeout, or install-wallet copy remains after success. Domain: The server returns access as owned or already entitled, not newly paid. Domain: No new page_entitlements duplicate, ledger debit, or author credit is created. Telemetry: The success path is visible without a duplicate conversion/payment signal." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: exercise-navigation-history + instruction: Use browser back, forward, and a fresh tab/deep link to return to the owned page. + expected: "UI: Navigation remains responsive and does not show a frozen loading state. UI: The reader can return to the publication detail and back to the paid page. Domain: No new charge is attempted in any navigation path." + evidence: + - screenshot + - trace + onFailure: stop +assertions: + - id: uiappearance-1 + type: visual + severity: fail + statement: Owned-page reread UI is stable on required desktop/mobile/wallet substrate. + - id: uiappearance-2 + type: visual + severity: fail + statement: History, reload, and deep link states do not leave overlapping wallet-help or loading messages. + - id: audienceintuition-1 + type: agent + severity: fail + statement: The returning reader can tell access is already owned. + - id: audienceintuition-2 + type: agent + severity: fail + statement: Any wallet prompt is understandable as identity/access, not a second purchase. + - id: customertrust-1 + type: security + severity: fail + statement: The flow does not create duplicate-charge anxiety. + - id: customertrust-2 + type: security + severity: fail + statement: There is no ambiguous retry button that could accidentally repurchase the same page. + - id: flowsuccess-1 + type: oracle + severity: fail + statement: The owned page renders by direct link, reload, and history navigation. + - id: flowsuccess-2 + type: oracle + severity: fail + statement: Before/after checks show no second charge, duplicate entitlement, or duplicate author ledger credit. + - id: telemetryobservability-1 + type: oracle + severity: fail + statement: Events for reread are queryable and distinguish owned access from a fresh paid conversion. + - id: telemetryobservability-2 + type: oracle + severity: fail + statement: If the telemetry model cannot distinguish owned reread from paid unlock, outcome must be warn and the run record must file a follow-up. + - id: reliabilityrepeatability-1 + type: oracle + severity: fail + statement: The flow passes in a clean browser context with the same wallet identity. + - id: reliabilityrepeatability-2 + type: oracle + severity: fail + statement: The run record documents the entitlement source without exposing private wallet material. + - id: performance-1 + type: performance + severity: fail + statement: Owned-page render after auth/access check <= 10s. + - id: performance-2 + type: performance + severity: fail + statement: Reload and history navigation should not exceed paid-flow thresholds. + - id: required-state-1 + type: oracle + severity: fail + statement: The selected reader identity has a prior entitlement for the selected publication/page. + tags: + - migrated-preflight + - id: required-state-2 + type: oracle + severity: fail + statement: Spend cap for this flow is zero because no new payment should occur. + tags: + - migrated-preflight + - id: required-state-3 + type: oracle + severity: fail + statement: Wallet substrate is available to authenticate the returning reader if required. + tags: + - migrated-preflight + - id: required-state-4 + type: oracle + severity: fail + statement: The operator has a way to compare before/after telemetry and logs for duplicate paid unlock or payment attempts. + tags: + - migrated-preflight +policy: + unsafeContent: stop + highImpactActions: require-approval + allowedHosts: + - papertrade.metanet.app + spendLimit: 0 + warnExitCode: 0 +remediation: + mode: manual + allowed: true + proposalOnly: true + requiredApprovers: 1 +uses: [] diff --git a/docs/proofrun/workflows/papertrade-wallet-failure-recovery.v1.proofrun.yaml b/docs/proofrun/workflows/papertrade-wallet-failure-recovery.v1.proofrun.yaml new file mode 100644 index 0000000..40c7ef2 --- /dev/null +++ b/docs/proofrun/workflows/papertrade-wallet-failure-recovery.v1.proofrun.yaml @@ -0,0 +1,223 @@ +apiVersion: proofrun.dev/v1 +kind: Workflow +metadata: + id: papertrade-wallet-failure-recovery + name: PaperTrade wallet missing, denied, timeout, and recovery + version: 1.0.0 + description: A reader who tries to continue past page 1 without a supported wallet, denies a wallet request, or experiences a wallet timeout. + labels: + migration: proofrunVersion-1 + repository: p2ppsr/PaperTrade + category: recovery +target: + type: web + url: https://papertrade.metanet.app + environment: production +matrix: + maxCases: 7 + exclude: + - {} + include: + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.chromium-desktop@1.0.0 + legacyDesktopBrowser: chrome + legacyMobileWallets: metanet-explorer-android + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.webkit-desktop@1.0.0 + legacyDesktopBrowser: safari + legacyMobileWallets: metanet-explorer-android + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.webkit-mobile@1.0.0 + legacyMobileBrowser: ios-safari + legacyMobileWallets: metanet-explorer-android + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.chromium-mobile@1.0.0 + legacyMobileBrowser: android-chrome + legacyMobileWallets: metanet-explorer-android + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: device.android-emulator@1.0.0 + legacyMobileSimulator: android-emulator + legacyMobileWallets: metanet-explorer-android + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: p2ppsr.metanet-client-macos@1.0.0 + legacyDesktopWallet: localhost-json-api-wallet-bridge + legacyMobileWallets: metanet-explorer-android + legacyNetworks: mainnet + - agent: openai-computer + profile: customer.impatient-newcomer@1.0.0 + accessibility: standard + device: p2ppsr.metanet-client-macos@1.0.0 + legacyDesktopWallet: bsv-browser + legacyMobileWallets: metanet-explorer-android + legacyNetworks: mainnet +capabilities: + - browser + - wallet.profile-restore +journeys: + - id: recovery + goal: PaperTrade wallet missing, denied, timeout, and recovery + role: A reader who tries to continue past page 1 without a supported wallet, denies a wallet request, or experiences a wallet timeout. + maxActions: 24 + maxSeconds: 90 + steps: + - id: missing-wallet-browser + instruction: Open page 2 in a clean browser with no supported wallet substrate. + expected: "UI: The page does not spin indefinitely. UI: The app explains that a BRC100-compatible wallet is needed. UI: The app offers useful next actions such as reading page 1, opening Help, or getting a supported wallet. Domain: No entitlement, payment, or ledger entry is created. Telemetry: reader.paid_page_access_started or wallet attempt telemetry may emit, followed by reader.paid_page_failed and/or wallet.action_failed." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: deny-wallet-prompt + instruction: After recording or resetting the PaperTrade wallet permission baseline, open page 2 in a supported wallet browser or bridge and deny/cancel the wallet prompt. + expected: "UI: The app returns to a clear recoverable failure state. UI: The user can retry or return to page 1. UI: The UI does not say the page is unlocked. Wallet: The permission baseline proves no relevant standing PaperTrade payment, basket, protocol, PACT, certificate, or manifest-derived permission could auto-complete the action, or the branch is marked blocked. Wallet: The wallet reports denial/cancel without submitting payment. Telemetry: wallet.action_failed and reader.paid_page_failed are emitted with safe failure context." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: timeout-wallet-request + instruction: Use a controlled unavailable wallet bridge, simulator state, or network block to cause a wallet timeout without approving payment. + expected: "UI: The app exits pending state within the documented timeout. UI: The message distinguishes timeout from missing wallet when possible. UI: The app does not keep a stale overlay or frozen control. Telemetry: wallet.request_failed or wallet.action_failed is emitted with timeout context." + evidence: + - screenshot + - trace + - log + - metric + onFailure: stop + - id: recover-with-valid-wallet + instruction: Restore the supported wallet substrate and retry only if the operator approves a spend under the paid-page purchase flow; otherwise retry should reach prompt without charging. + expected: "UI: Retry starts a fresh wallet request and does not reuse stale failure state. UI: The reader can return to page 1 and continue browsing. Domain: No payment occurs unless the operator explicitly continues under the paid-page purchase ProofRun." + evidence: + - screenshot + - trace + onFailure: stop +assertions: + - id: uiappearance-1 + type: visual + severity: fail + statement: Failure states fit mobile and desktop layouts without clipped wallet-help text or hidden buttons. + - id: uiappearance-2 + type: visual + severity: fail + statement: Retry, page 1, help, and wallet setup actions remain visible and tappable. + - id: audienceintuition-1 + type: agent + severity: fail + statement: The target reader can understand whether the problem is missing wallet, denied request, timeout, or retryable wallet connection. + - id: audienceintuition-2 + type: agent + severity: fail + statement: The app avoids implementation-only errors as primary user text. + - id: customertrust-1 + type: security + severity: fail + statement: The reader is never left wondering whether a payment happened. + - id: customertrust-2 + type: security + severity: fail + statement: The app does not invite blind repeated clicks while a payment may be pending. + - id: flowsuccess-1 + type: oracle + severity: fail + statement: Each failure branch produces no entitlement, no author ledger credit, and no platform commission. + - id: flowsuccess-2 + type: oracle + severity: fail + statement: Recovery from a failure starts from clean UI state. + - id: telemetryobservability-1 + type: oracle + severity: fail + statement: Failure telemetry is distinguishable by cause where available. + - id: telemetryobservability-2 + type: oracle + severity: fail + statement: Logs and telemetry contain no raw auth signatures, raw transactions, cookies, JWTs, private keys, or seed material. + - id: reliabilityrepeatability-1 + type: oracle + severity: fail + statement: Missing-wallet and denial branches can be repeated from a clean session. + - id: reliabilityrepeatability-2 + type: oracle + severity: fail + statement: Timeout branch documents the exact simulator/bridge condition used. + - id: performance-1 + type: performance + severity: fail + statement: Missing-wallet guidance appears <= 10s. + - id: performance-2 + type: performance + severity: fail + statement: Denied prompt recovery appears <= 15s. + - id: performance-3 + type: performance + severity: fail + statement: Timeout recovery appears within the product timeout and never exceeds 45s without a progress state. + - id: required-state-1 + type: oracle + severity: fail + statement: A clean non-wallet browser context is available. + tags: + - migrated-preflight + - id: required-state-2 + type: oracle + severity: fail + statement: A wallet substrate that can deny/cancel a prompt is available for denial testing, or the branch is marked blocked. + tags: + - migrated-preflight + - id: required-state-3 + type: oracle + severity: fail + statement: The wallet permission baseline for papertrade.metanet.app is captured before the denial/timeout branches, including payments/spending, baskets, grouped protocols, PACT permissions, certificate access, and manifest-derived grants that may affect page access. + tags: + - migrated-preflight + - id: required-state-4 + type: oracle + severity: fail + statement: For zero-spend branches, existing PaperTrade permissions that could auto-complete paid page access are revoked, or an isolated wallet/profile with no relevant PaperTrade permission is used before opening an unowned paid page. + tags: + - migrated-preflight + - id: required-state-5 + type: oracle + severity: fail + statement: A controlled timeout or unavailable wallet bridge can be created without approving payment, or the branch is marked blocked. + tags: + - migrated-preflight + - id: required-state-6 + type: oracle + severity: fail + statement: The selected publication has a paid page 2. + tags: + - migrated-preflight +policy: + unsafeContent: stop + highImpactActions: deny + allowedHosts: + - papertrade.metanet.app + spendLimit: 0 + warnExitCode: 0 +remediation: + mode: manual + allowed: true + proposalOnly: true + requiredApprovers: 1 +uses: []