OverviewFilesCommitsIssuesDocsReleasesPeers

pearbrowser-desktop commits / 345179f

migrate browser catalog release evidence to native packages
345179fd25253b136cec3f05c8ec003ac9706ae9
by bigdestiny2 <33146784+bigdestiny2@users.noreply.github.com> · 2026-07-22T23:38:43.000Z

Changed files (4) +38 -34

scripts/catalog-bee.sample.json +9 -5
……@@ -6,7 +6,8 @@
66 "id": "keet",
77 "name": "Keet",
88 "description": "End-to-end encrypted P2P chat, voice, and video calls by Holepunch.",
9 "link": "pear://oeeoz3w6fjjt7bym3ndpa6hhicm8f8naxyk11z4iypeoupn6jzpo",
9 "legacyMigrationId": "oeeoz3w6fjjt7bym3ndpa6hhicm8f8naxyk11z4iypeoupn6jzpo",
10 "nativeDelivery": { "status": "migration-required" },
1011 "author": "Holepunch",
1112 "categories": ["chat", "communication"]
1213 },
……@@ -14,15 +15,17 @@
1415 "id": "pearpass",
1516 "name": "PearPass",
1617 "description": "Peer-to-peer password manager from Tether — synced across devices without a cloud.",
17 "link": "pear://tywsat7gz8m65ejx4zjn3773pbdc4j8m66tukis8dgzekraymtzo",
18 "legacyMigrationId": "tywsat7gz8m65ejx4zjn3773pbdc4j8m66tukis8dgzekraymtzo",
19 "nativeDelivery": { "status": "migration-required" },
1820 "author": "Tether",
1921 "categories": ["security", "utilities"]
2022 },
2123 {
2224 "id": "hiveworm",
2325 "name": "HiveWorm",
24 "description": "Perpetual P2P life-sim — runs as a Pear app via swarm.v1.",
25 "link": "pear://d1xbkcpcbi1xa8dexp49rsendra5r67w3qh5a9k8t44oemm4k16y",
26 "description": "Perpetual P2P life-sim — native v3 package migration required.",
27 "legacyMigrationId": "d1xbkcpcbi1xa8dexp49rsendra5r67w3qh5a9k8t44oemm4k16y",
28 "nativeDelivery": { "status": "migration-required" },
2629 "author": "HiveWorm",
2730 "categories": ["games"]
2831 },
……@@ -30,7 +33,8 @@
3033 "id": "anongpt",
3134 "name": "anonGPT",
3235 "description": "Private P2P AI chat — pay-per-inference from a HiveMind seller, with signed receipts.",
33 "link": "pear://rpzh3fsgg38kfir9nmae7x3o8ubofddzzixr5js4mxd6a6drb6wo",
36 "legacyMigrationId": "rpzh3fsgg38kfir9nmae7x3o8ubofddzzixr5js4mxd6a6drb6wo",
37 "nativeDelivery": { "status": "migration-required" },
3438 "author": "anonGPT",
3539 "categories": ["ai"]
3640 }
scripts/release-rpc-story-smoke.mjs +24 -24
……@@ -51,7 +51,7 @@ const DEFAULT_CATALOGS = [
5151]
5252const REQUIRED_FEATURED = ['Keet', 'PearPass', 'anonGPT', 'Paste', 'Peercord']
5353const CATALOG_SEARCH_TERMS = ['peercord', 'peerit', 'keet', 'paste']
54const PEERCORD_LINK = 'pear://wmir47w7mai3b1skj66mx7fzso6k6o91kipaney7gtt69npimouy'
54const PEERCORD_MIGRATION_ID = 'wmir47w7mai3b1skj66mx7fzso6k6o91kipaney7gtt69npimouy'
5555const RELEASE_EVIDENCE_SECTION = 'Desktop GUI And User Stories'
5656
5757function parseArgs (argv) {
……@@ -472,20 +472,20 @@ function assertCatalogues (catalogResult) {
472472
473473 const peercord = byName.get('peercord')
474474 if (!peercord) throw new Error('Peercord missing from catalogue')
475 if (peercord.type !== 'standalone') throw new Error(`Peercord type mismatch: expected standalone, got ${peercord.type || '(missing)'}`)
476 if (peercord.link !== PEERCORD_LINK) throw new Error(`Peercord link mismatch: ${peercord.link || '(missing)'}`)
477 if (peercord.driveKey) throw new Error('Peercord unexpectedly has a driveKey; standalone pear:// apps should launch in a window')
475 if (peercord.legacyMigrationId !== PEERCORD_MIGRATION_ID) throw new Error(`Peercord migration id mismatch: ${peercord.legacyMigrationId || '(missing)'}`)
476 if (peercord.nativeDelivery?.status !== 'migration-required') throw new Error('Peercord must require a verified native v3 package')
477 if (peercord.link || peercord.driveKey) throw new Error('Peercord must not expose a remote executable or browsable content target')
478478
479479 return {
480480 catalogs: catalogs.length,
481481 apps: apps.length,
482482 featured,
483483 peercord: {
484 type: peercord.type,
485 link: peercord.link,
484 nativeDelivery: peercord.nativeDelivery,
485 legacyMigrationId: peercord.legacyMigrationId,
486486 sourceUrl: peercord.sourceUrl || null,
487487 license: peercord.license || null,
488 runMode: 'window'
488 runMode: 'migration-required'
489489 }
490490 }
491491}
……@@ -892,23 +892,23 @@ async function runSafeCatalogueAppOpenStory (ws, args, catalogResult) {
892892
893893function runFeaturedAppRegressionStory (catalogResult, safeOpen) {
894894 const apps = Array.isArray(catalogResult?.apps) ? catalogResult.apps : []
895 const standaloneTargets = REQUIRED_FEATURED
895 const migrationRequired = REQUIRED_FEATURED
896896 .map((name) => findAppByName(apps, name))
897897 .filter(Boolean)
898 .filter((app) => /^pear:\/\//i.test(String(app.link || '')))
898 .filter((app) => app.nativeDelivery?.status === 'migration-required')
899899 .map((app) => ({
900900 name: app.name || app.id,
901 type: app.type || 'standalone',
902 link: app.link,
901 legacyMigrationId: app.legacyMigrationId || null,
902 nativeDelivery: app.nativeDelivery,
903903 action: launchActionForApp(app)
904904 }))
905905
906 if (!standaloneTargets.some((app) => sameNameOrId(app, 'keet'))) {
907 throw new Error('featured app regression story could not verify Keet window launch target')
906 if (!migrationRequired.some((app) => sameNameOrId(app, 'keet'))) {
907 throw new Error('featured app regression story could not verify Keet migration state')
908908 }
909 for (const app of standaloneTargets) {
910 if (app.action.primary !== 'open-window') {
911 throw new Error(`featured app regression launch action mismatch for ${app.name}`)
909 for (const app of migrationRequired) {
910 if (app.action.primary !== 'migration-required' || !app.legacyMigrationId) {
911 throw new Error(`featured app regression migration state mismatch for ${app.name}`)
912912 }
913913 }
914914
……@@ -920,8 +920,8 @@ function runFeaturedAppRegressionStory (catalogResult, safeOpen) {
920920 bytes: safeOpen.bytes,
921921 action: safeOpen.action
922922 },
923 standaloneTargets,
924 automationScope: 'safe featured Hyperdrive open plus standalone pear:// target validation; no third-party trust approval'
923 migrationRequired,
924 automationScope: 'safe featured Hyperdrive open plus non-executable native migration-state validation; no third-party code execution'
925925 }
926926}
927927
……@@ -1061,12 +1061,12 @@ function launchActionForApp (app) {
10611061 const link = String(app?.link || '').trim()
10621062 const driveKey = String(app?.driveKey || '').trim().toLowerCase()
10631063 const hasDrive = isHyperDriveKey(driveKey)
1064 if (/^(pear|file):\/\//i.test(link)) {
1064 if (app?.nativeDelivery?.status === 'migration-required') {
10651065 return {
1066 primary: 'open-window',
1067 openPage: hasDrive,
1066 primary: 'migration-required',
1067 openPage: false,
10681068 runInTab: false,
1069 reason: `${app?.type || 'standalone'} pear/file app`
1069 reason: 'verified native v3 package required'
10701070 }
10711071 }
10721072 if (/^hyper:\/\//i.test(link) || hasDrive) {
……@@ -1139,7 +1139,7 @@ function buildReleaseEvidence (result) {
11391139 add('Latest-app-without-download story', `release RPC desktop-gui smoke: opened ${desktop.latestAppWithoutDownload.name} from catalogue row via Browse at ${shortHyper(desktop.latestAppWithoutDownload.url)}, HTTP ${desktop.latestAppWithoutDownload.statusCode} ${desktop.latestAppWithoutDownload.bytes} bytes, no project page download or manual update`)
11401140 }
11411141 if (desktop?.featuredAppRegression) {
1142 add('Existing featured app regression', `release RPC desktop-gui smoke: safe featured app ${desktop.featuredAppRegression.safeOpenedFeaturedApp.name} opened via Browse HTTP ${desktop.featuredAppRegression.safeOpenedFeaturedApp.statusCode}; standalone featured targets ${desktop.featuredAppRegression.standaloneTargets.map((app) => app.name).join(', ')} remain pear window targets with no trust approval automated`)
1142 add('Existing featured app regression', `release RPC desktop-gui smoke: safe featured app ${desktop.featuredAppRegression.safeOpenedFeaturedApp.name} opened via Browse HTTP ${desktop.featuredAppRegression.safeOpenedFeaturedApp.statusCode}; legacy native records ${desktop.featuredAppRegression.migrationRequired.map((app) => app.name).join(', ')} require verified packages and no code execution was automated`)
11431143 }
11441144 if (desktop?.nostrTrustedContact) {
11451145 add('Nostr trusted-contact story', `release RPC desktop-gui smoke: Nostr trust proof exposed ${desktop.nostrTrustedContact.visibleEvents} attested contact event via ${desktop.nostrTrustedContact.trustedVia} and quarantined ${desktop.nostrTrustedContact.hidden.quarantined} revoked or forged event(s)`)
……@@ -1242,7 +1242,7 @@ function printHuman (result) {
12421242 console.log(` homepage: HTTP ${result.homepage.statusCode}, ${result.homepage.bytes} bytes${result.homepage.title ? `, "${result.homepage.title}"` : ''}`)
12431243 console.log(` catalogues: ${result.catalog.catalogs} loaded, ${result.catalog.apps} aggregated apps`)
12441244 console.log(` featured: ${result.catalog.featured.map((app) => app.name).join(', ')}`)
1245 console.log(` Peercord: ${result.catalog.peercord.type}, ${result.catalog.peercord.runMode}, ${result.catalog.peercord.link}`)
1245 console.log(` Peercord: ${result.catalog.peercord.runMode}, ${result.catalog.peercord.legacyMigrationId}`)
12461246 if (result.localStories) {
12471247 console.log(` local search: ${result.localStories.search.results} result(s), doc ${result.localStories.search.docId}`)
12481248 console.log(` naming: ${result.localStories.naming.curated.name} curated + ${result.localStories.naming.petname.name} petname`)
scripts/verify-live-catalog.js +3 -3
……@@ -136,9 +136,9 @@ async function main () {
136136
137137 const peercord = byId.get('peercord')
138138 if (peercord) {
139 if (peercord.link !== 'pear://wmir47w7mai3b1skj66mx7fzso6k6o91kipaney7gtt69npimouy') fail('Peercord link mismatch')
140 if (peercord.driveKey) fail('Peercord should be pear:// standalone without a Hyperdrive driveKey')
141 if (peercord.type !== 'standalone') fail(`Peercord type mismatch: expected standalone, got ${peercord.type || '(missing)'}`)
139 if (peercord.legacyMigrationId !== 'wmir47w7mai3b1skj66mx7fzso6k6o91kipaney7gtt69npimouy') fail('Peercord migration id mismatch')
140 if (peercord.link || peercord.driveKey) fail('Peercord must not expose a remote executable or browsable content target')
141 if (peercord.nativeDelivery?.status !== 'migration-required') fail('Peercord must require a verified native v3 package')
142142 if (peercord.sourceUrl !== 'https://git.churchofmalware.org/mastercodeon/Peercord') fail('Peercord sourceUrl mismatch')
143143 if (peercord.license !== 'GPL-3.0') fail('Peercord license mismatch')
144144 }
test/release-packaging.test.js +2 -2
……@@ -2247,8 +2247,8 @@ test('release story smoke covers browse, catalogue, local stories, and opt-in si
22472247 assert.match(releaseStorySmoke, /Library\/session story/)
22482248 assert.match(releaseStorySmoke, /PearBrowser\|Pear Browser/)
22492249 assert.match(releaseStorySmoke, /REQUIRED_FEATURED = \['Keet', 'PearPass', 'anonGPT', 'Paste', 'Peercord'\]/)
2250 assert.match(releaseStorySmoke, /PEERCORD_LINK/)
2251 assert.match(releaseStorySmoke, /runMode: 'window'/)
2250 assert.match(releaseStorySmoke, /PEERCORD_MIGRATION_ID/)
2251 assert.match(releaseStorySmoke, /runMode: 'migration-required'/)
22522252 assert.doesNotMatch(releaseStorySmoke, /CMD_LAUNCH_PEAR_LINK/)
22532253 assert.doesNotMatch(releaseStorySmoke, /CMD_RUN_APP_IN_TAB/)
22542254})