@meddleware/seal-ui 0.0.12 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +17 -12
- package/src/App.vue +2 -1
- package/src/components/SealView.vue +9 -8
- package/src/manifest-guard.ts +30 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meddleware/seal-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"homepage": "https://docs.meddleware.co.uk/blockchain/sui/sealed-storage/",
|
|
5
5
|
"description": "Standalone Vue 3 SPA for Sealed Storage — client-side Seal encryption + access-gated, decentralised Walrus storage on Sui.",
|
|
6
6
|
"author": "MeddleWare <meddleware@proton.me>",
|
|
@@ -32,26 +32,31 @@
|
|
|
32
32
|
"dev": "vite",
|
|
33
33
|
"build": "vue-tsc --noEmit && vite build",
|
|
34
34
|
"preview": "vite preview",
|
|
35
|
-
"type-check": "vue-tsc --noEmit"
|
|
35
|
+
"type-check": "vue-tsc --noEmit",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"test:watch": "vitest"
|
|
36
38
|
},
|
|
37
39
|
"publishConfig": {
|
|
38
40
|
"access": "public"
|
|
39
41
|
},
|
|
40
42
|
"dependencies": {
|
|
41
|
-
"@meddleware/design-tokens": "^0.1.
|
|
42
|
-
"@meddleware/seal-client": "^0.0.
|
|
43
|
-
"@meddleware/ui": "^0.1.
|
|
44
|
-
"@meddleware/wallet-adapter": "^0.0.
|
|
45
|
-
"@mysten/sui": "^2.
|
|
46
|
-
"@mysten/wallet-standard": "^0.
|
|
47
|
-
"vue": "^3.5.
|
|
43
|
+
"@meddleware/design-tokens": "^0.1.3",
|
|
44
|
+
"@meddleware/seal-client": "^0.0.5",
|
|
45
|
+
"@meddleware/ui": "^0.1.13",
|
|
46
|
+
"@meddleware/wallet-adapter": "^0.0.6",
|
|
47
|
+
"@mysten/sui": "^2.31.0",
|
|
48
|
+
"@mysten/wallet-standard": "^0.21.0",
|
|
49
|
+
"vue": "^3.5.43"
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
50
52
|
"@types/node": "~24.12.2",
|
|
51
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
53
|
+
"@vitejs/plugin-vue": "^6.0.9",
|
|
54
|
+
"@vue/test-utils": "^2.5.1",
|
|
55
|
+
"jsdom": "^30.1.0",
|
|
52
56
|
"typescript": "~6.0.0",
|
|
53
|
-
"vite": "^8.
|
|
54
|
-
"
|
|
57
|
+
"vite": "^8.3.0",
|
|
58
|
+
"vitest": "~5.0.1",
|
|
59
|
+
"vue-tsc": "~3.3.11"
|
|
55
60
|
},
|
|
56
61
|
"engines": {
|
|
57
62
|
"node": "^22.18.0 || >=24.12.0"
|
package/src/App.vue
CHANGED
|
@@ -7,6 +7,7 @@ import SealView from './components/SealView.vue'
|
|
|
7
7
|
|
|
8
8
|
const { mode, set } = useColorMode('dark')
|
|
9
9
|
const DOCS_URL = import.meta.env.VITE_DOCS_URL || 'https://docs.meddleware.co.uk/blockchain/sui/sealed-storage/'
|
|
10
|
+
const DEV_URL = import.meta.env.VITE_DEV_URL || 'https://dev.meddleware.co.uk/sui/sealed-storage/'
|
|
10
11
|
</script>
|
|
11
12
|
|
|
12
13
|
<template>
|
|
@@ -23,7 +24,7 @@ const DOCS_URL = import.meta.env.VITE_DOCS_URL || 'https://docs.meddleware.co.uk
|
|
|
23
24
|
|
|
24
25
|
<SealView />
|
|
25
26
|
|
|
26
|
-
<AppFooter :docs-url="DOCS_URL" />
|
|
27
|
+
<AppFooter :docs-url="DOCS_URL" :dev-url="DEV_URL" />
|
|
27
28
|
</div>
|
|
28
29
|
</template>
|
|
29
30
|
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
type SealedContentPointer,
|
|
18
18
|
type FieldSuggestion,
|
|
19
19
|
} from '@meddleware/seal-client'
|
|
20
|
+
import { checkManifestForNetwork } from '../manifest-guard.js'
|
|
20
21
|
import { WalletGuard } from '@meddleware/wallet-adapter'
|
|
21
22
|
import { useWallet, getSuiClient } from '../wallet.js'
|
|
22
23
|
import { registry, getSealController } from '../seal.js'
|
|
@@ -175,14 +176,13 @@ function downloadManifest(): void {
|
|
|
175
176
|
// ── Decrypt ──────────────────────────────────────────────────────────────────
|
|
176
177
|
const decManifestText = ref('')
|
|
177
178
|
const decValues = ref<Record<string, string | boolean>>({})
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
})
|
|
179
|
+
// Validate the pasted/loaded manifest through the shared schema guard (rejects malformed shapes)
|
|
180
|
+
// AND enforce that it targets the network this app is built for — a manifest sealed on another
|
|
181
|
+
// network references a package + committee that don't exist here and can never decrypt. The
|
|
182
|
+
// `decManifestError` is surfaced next to the input so a rejection explains itself.
|
|
183
|
+
const decCheck = computed(() => checkManifestForNetwork(decManifestText.value, NETWORK))
|
|
184
|
+
const decManifest = computed<SealedManifest | null>(() => decCheck.value.manifest)
|
|
185
|
+
const decManifestError = computed<string | null>(() => decCheck.value.error)
|
|
186
186
|
const decProvider = computed(() =>
|
|
187
187
|
decManifest.value ? (providers.find((p) => p.type === decManifest.value?.policyType) ?? null) : null,
|
|
188
188
|
)
|
|
@@ -494,6 +494,7 @@ async function performUnlock(item: SealedContentPointer): Promise<void> {
|
|
|
494
494
|
/>
|
|
495
495
|
</label>
|
|
496
496
|
</template>
|
|
497
|
+
<p v-else-if="decManifestError" class="muted">{{ decManifestError }}</p>
|
|
497
498
|
<p v-else-if="decManifestText.trim()" class="muted">Unrecognised or invalid manifest.</p>
|
|
498
499
|
|
|
499
500
|
<button class="primary" :disabled="busy || !decProvider" @click="performDecrypt">
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { parseSealedManifest, type SealedManifest } from '@meddleware/seal-client'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Result of validating a pasted/loaded manifest: either the parsed manifest, or a human-readable
|
|
5
|
+
* reason it was rejected. An empty input is `{ manifest: null, error: null }` (nothing to show yet).
|
|
6
|
+
*/
|
|
7
|
+
export type ManifestCheck =
|
|
8
|
+
| { manifest: SealedManifest; error: null }
|
|
9
|
+
| { manifest: null; error: string | null }
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Validate a manifest string for use on `network`. Rejects a malformed shape (via the shared
|
|
13
|
+
* `parseSealedManifest` schema guard) and a manifest sealed for a different network — the latter
|
|
14
|
+
* references a policy package + key-server committee that don't exist here and can never decrypt.
|
|
15
|
+
*/
|
|
16
|
+
export function checkManifestForNetwork(text: string, network: string): ManifestCheck {
|
|
17
|
+
if (!text.trim()) return { manifest: null, error: null }
|
|
18
|
+
try {
|
|
19
|
+
const manifest = parseSealedManifest(text)
|
|
20
|
+
if (manifest.network !== network) {
|
|
21
|
+
return {
|
|
22
|
+
manifest: null,
|
|
23
|
+
error: `This manifest is for '${manifest.network}', but this app is on '${network}'. It cannot be decrypted here.`,
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return { manifest, error: null }
|
|
27
|
+
} catch (e) {
|
|
28
|
+
return { manifest: null, error: e instanceof Error ? e.message : 'Invalid manifest.' }
|
|
29
|
+
}
|
|
30
|
+
}
|