@agimon-ai/doompi-web 0.0.1-alpha.3 → 0.0.1-alpha.4
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/README.md +57 -29
- package/dist/pwa/icon-192.png +0 -0
- package/dist/pwa/icon-512.png +0 -0
- package/dist/pwa/index.html +104 -0
- package/dist/pwa/manifest.webmanifest +23 -0
- package/dist/pwa/pwa.js +21 -0
- package/dist/pwa/sw.js +2 -0
- package/dist/src/adapters/bundlePublication.cjs +2 -0
- package/dist/src/adapters/bundlePublication.cjs.map +1 -0
- package/dist/src/adapters/bundlePublication.mjs +2 -0
- package/dist/src/adapters/bundlePublication.mjs.map +1 -0
- package/dist/src/adapters/httpServer.cjs +2 -1
- package/dist/src/adapters/httpServer.cjs.map +1 -1
- package/dist/src/adapters/httpServer.d.cts.map +1 -1
- package/dist/src/adapters/httpServer.d.mts.map +1 -1
- package/dist/src/adapters/httpServer.mjs +2 -1
- package/dist/src/adapters/httpServer.mjs.map +1 -1
- package/dist/src/adapters/remoteAccess.cjs +1 -1
- package/dist/src/adapters/remoteAccess.cjs.map +1 -1
- package/dist/src/adapters/remoteAccess.mjs +1 -1
- package/dist/src/adapters/remoteAccess.mjs.map +1 -1
- package/dist/src/adapters/remoteRoutes.cjs +1 -1
- package/dist/src/adapters/remoteRoutes.cjs.map +1 -1
- package/dist/src/adapters/remoteRoutes.mjs +1 -1
- package/dist/src/adapters/remoteRoutes.mjs.map +1 -1
- package/dist/src/adapters/sessionHub.cjs +1 -1
- package/dist/src/adapters/sessionHub.cjs.map +1 -1
- package/dist/src/adapters/sessionHub.mjs +1 -1
- package/dist/src/adapters/sessionHub.mjs.map +1 -1
- package/dist/src/adapters/tunnelProcess.cjs +1 -1
- package/dist/src/adapters/tunnelProcess.cjs.map +1 -1
- package/dist/src/adapters/tunnelProcess.mjs +1 -1
- package/dist/src/adapters/tunnelProcess.mjs.map +1 -1
- package/dist/src/adapters/webBundler.cjs +1 -1
- package/dist/src/adapters/webBundler.cjs.map +1 -1
- package/dist/src/adapters/webBundler.d.cts +1 -1
- package/dist/src/adapters/webBundler.d.mts +1 -1
- package/dist/src/adapters/webBundler.mjs +1 -1
- package/dist/src/adapters/webBundler.mjs.map +1 -1
- package/dist/src/adapters/webHubPluginLoader.cjs +1 -1
- package/dist/src/adapters/webHubPluginLoader.cjs.map +1 -1
- package/dist/src/adapters/webHubPluginLoader.mjs +1 -1
- package/dist/src/adapters/webHubPluginLoader.mjs.map +1 -1
- package/dist/src/adapters/webPush.cjs +2 -0
- package/dist/src/adapters/webPush.cjs.map +1 -0
- package/dist/src/adapters/webPush.mjs +2 -0
- package/dist/src/adapters/webPush.mjs.map +1 -0
- package/dist/src/services/fileMedia.cjs +1 -1
- package/dist/src/services/fileMedia.cjs.map +1 -1
- package/dist/src/services/fileMedia.mjs +1 -1
- package/dist/src/services/fileMedia.mjs.map +1 -1
- package/dist/src/services/pairingFlow.cjs +1 -1
- package/dist/src/services/pairingFlow.cjs.map +1 -1
- package/dist/src/services/pairingFlow.mjs +1 -1
- package/dist/src/services/pairingFlow.mjs.map +1 -1
- package/dist/src/services/pairingPage.cjs +188 -74
- package/dist/src/services/pairingPage.cjs.map +1 -1
- package/dist/src/services/pairingPage.mjs +188 -74
- package/dist/src/services/pairingPage.mjs.map +1 -1
- package/dist/src/services/remoteGuardPolicy.cjs +1 -1
- package/dist/src/services/remoteGuardPolicy.cjs.map +1 -1
- package/dist/src/services/remoteGuardPolicy.mjs +1 -1
- package/dist/src/services/remoteGuardPolicy.mjs.map +1 -1
- package/dist/src/services/webauthnPolicy.cjs +1 -1
- package/dist/src/services/webauthnPolicy.cjs.map +1 -1
- package/dist/src/services/webauthnPolicy.mjs +1 -1
- package/dist/src/services/webauthnPolicy.mjs.map +1 -1
- package/dist/src/types/hub.cjs.map +1 -1
- package/dist/src/types/hub.d.cts +1 -1
- package/dist/src/types/hub.d.cts.map +1 -1
- package/dist/src/types/hub.d.mts +1 -1
- package/dist/src/types/hub.d.mts.map +1 -1
- package/dist/src/types/hub.mjs.map +1 -1
- package/dist/src/types/remoteAccess.cjs +1 -1
- package/dist/src/types/remoteAccess.cjs.map +1 -1
- package/dist/src/types/remoteAccess.d.cts.map +1 -1
- package/dist/src/types/remoteAccess.d.mts.map +1 -1
- package/dist/src/types/remoteAccess.mjs +1 -1
- package/dist/src/types/remoteAccess.mjs.map +1 -1
- package/dist/src/types/session.cjs +1 -1
- package/dist/src/types/session.mjs +1 -1
- package/dist/src/types/session.mjs.map +1 -1
- package/dist/web/assets/{CodeEditorView-CP55qjoR.js → CodeEditorView-ZJ3fgCgP.js} +3 -3
- package/dist/web/assets/{CodeEditorView-CP55qjoR.js.map → CodeEditorView-ZJ3fgCgP.js.map} +1 -1
- package/dist/web/assets/{dist-Gdc8iniF.js → dist-4CpY4--O.js} +2 -2
- package/dist/web/assets/{dist-Gdc8iniF.js.map → dist-4CpY4--O.js.map} +1 -1
- package/dist/web/assets/{dist-C7QLpOTK.js → dist-BAbw37G4.js} +2 -2
- package/dist/web/assets/{dist-C7QLpOTK.js.map → dist-BAbw37G4.js.map} +1 -1
- package/dist/web/assets/{dist-CElJaC8s.js → dist-BCw5Th7z.js} +2 -2
- package/dist/web/assets/{dist-CElJaC8s.js.map → dist-BCw5Th7z.js.map} +1 -1
- package/dist/web/assets/{dist-eZCftY6T.js → dist-BZRRewb_.js} +1 -1
- package/dist/web/assets/{dist-TyTwU387.js → dist-B_rHH1XB.js} +2 -2
- package/dist/web/assets/{dist-TyTwU387.js.map → dist-B_rHH1XB.js.map} +1 -1
- package/dist/web/assets/{dist-GONoz8to.js → dist-BhGCoeQZ.js} +2 -2
- package/dist/web/assets/{dist-GONoz8to.js.map → dist-BhGCoeQZ.js.map} +1 -1
- package/dist/web/assets/{dist-DgVFo7X3.js → dist-C60KVFlU.js} +2 -2
- package/dist/web/assets/{dist-DgVFo7X3.js.map → dist-C60KVFlU.js.map} +1 -1
- package/dist/web/assets/{dist-B0inTUnL.js → dist-Cj5gWlhe.js} +2 -2
- package/dist/web/assets/{dist-B0inTUnL.js.map → dist-Cj5gWlhe.js.map} +1 -1
- package/dist/web/assets/{dist-Bqd73gXk.js → dist-DCwjnz7l.js} +2 -2
- package/dist/web/assets/{dist-Bqd73gXk.js.map → dist-DCwjnz7l.js.map} +1 -1
- package/dist/web/assets/{dist-Cwzviw_U.js → dist-DW9ZoBfU.js} +2 -2
- package/dist/web/assets/{dist-Cwzviw_U.js.map → dist-DW9ZoBfU.js.map} +1 -1
- package/dist/web/assets/index-DqvMDNrH.js +99 -0
- package/dist/web/assets/index-DqvMDNrH.js.map +1 -0
- package/dist/web/assets/index-Dx8DvA-4.css +2 -0
- package/dist/web/index.html +3 -2
- package/package.json +14 -11
- package/src/adapters/bundlePublication.ts +80 -0
- package/src/adapters/httpServer.ts +179 -10
- package/src/adapters/remoteAccess.ts +46 -12
- package/src/adapters/remoteRoutes.ts +13 -3
- package/src/adapters/sessionHub.ts +67 -4
- package/src/adapters/tunnelProcess.ts +192 -17
- package/src/adapters/webBundler.ts +2 -2
- package/src/adapters/webHubPluginLoader.ts +6 -2
- package/src/adapters/webPush.ts +127 -0
- package/src/pwa/bundleCache.ts +79 -0
- package/src/pwa/index.html +104 -0
- package/src/pwa/main.ts +163 -0
- package/src/pwa/public/icon-192.png +0 -0
- package/src/pwa/public/icon-512.png +0 -0
- package/src/pwa/public/manifest.webmanifest +23 -0
- package/src/pwa/qrScanner.ts +65 -0
- package/src/pwa/serviceWorker.ts +261 -0
- package/src/pwa/workerClient.ts +60 -0
- package/src/services/fileMedia.ts +1 -0
- package/src/services/pairingFlow.ts +13 -10
- package/src/services/pairingPage.ts +204 -81
- package/src/services/remoteGuardPolicy.ts +9 -7
- package/src/services/webauthnPolicy.ts +1 -0
- package/src/types/hub.ts +16 -3
- package/src/types/remoteAccess.ts +12 -0
- package/src/web/app/Providers.tsx +2 -0
- package/src/web/app/protocolRuntime.ts +3 -2
- package/src/web/app/sessionRuntime.ts +31 -3
- package/src/web/features/activity/ActivityDock.tsx +4 -4
- package/src/web/features/remote/RemoteAccessPairing.tsx +25 -3
- package/src/web/features/session/Composer.tsx +98 -77
- package/src/web/features/session/MentionPreviews.tsx +65 -14
- package/src/web/features/session/QueueSheet.tsx +113 -0
- package/src/web/features/session/Timeline.tsx +46 -21
- package/src/web/features/session/ToolCard.tsx +151 -8
- package/src/web/features/sessions/ResumeSessionDialog.tsx +150 -0
- package/src/web/features/sessions/SessionRail.tsx +8 -9
- package/src/web/features/settings/NotificationSettings.tsx +35 -10
- package/src/web/features/status/TopBar.tsx +12 -66
- package/src/web/index.html +1 -0
- package/src/web/lib/commands.ts +4 -0
- package/src/web/lib/composition.ts +57 -9
- package/src/web/lib/hubApi.ts +49 -1
- package/src/web/lib/livePush.ts +116 -0
- package/src/web/lib/pluginSlotProps.ts +2 -0
- package/src/web/lib/protocolTimeline.ts +19 -3
- package/src/web/lib/remoteApi.ts +27 -3
- package/src/web/lib/sessionAsset.ts +30 -0
- package/src/web/lib/sessionModel.ts +53 -1
- package/src/web/routes/CockpitPage.tsx +12 -4
- package/src/web/stores/composerStore.ts +92 -0
- package/src/web/stores/remoteAccessStore.ts +27 -3
- package/src/web/stores/sessionStore.ts +81 -12
- package/src/web/stores/usePluginSlotProps.ts +20 -9
- package/dist/web/assets/index-BqJnbtrI.css +0 -2
- package/dist/web/assets/index-Ck8t7U8J.js +0 -98
- package/dist/web/assets/index-Ck8t7U8J.js.map +0 -1
package/README.md
CHANGED
|
@@ -120,8 +120,27 @@ perform the handshake itself: `attach` frames sent from the browser are refused.
|
|
|
120
120
|
them.
|
|
121
121
|
- Subagent, workflow, and runner surfaces report summaries only; per-run detail has no RPC source
|
|
122
122
|
to render from yet.
|
|
123
|
-
-
|
|
124
|
-
|
|
123
|
+
- Open pages show full live browser notifications. An installed paired PWA can also receive a generic
|
|
124
|
+
zero-TTL Web Push alert while closed. There is no durable subscription database, outbox, replay, or
|
|
125
|
+
historical delivery.
|
|
126
|
+
|
|
127
|
+
## iPhone Home Screen app
|
|
128
|
+
|
|
129
|
+
Use a stable named HTTPS tunnel such as `doompi.agimon.win`. Quick-tunnel hostnames rotate, so they cannot
|
|
130
|
+
provide durable PWA identity, passkeys, or reliable Push subscriptions. Open `/pair` in Safari, add it to the
|
|
131
|
+
Home Screen, then launch the installed app and scan the QR shown by the host.
|
|
132
|
+
|
|
133
|
+
The install shell, scanner, manifest, and verifier worker are package-owned. The QR pins the host signing key
|
|
134
|
+
and minimum bundle revision. The worker verifies every host and plugin asset before committing it to the
|
|
135
|
+
active cache, and the host never serves its SPA directly. A failed update keeps the last-known-good bundle.
|
|
136
|
+
Signer loss, signer rotation, or a host/container transition requires explicit fingerprint confirmation and
|
|
137
|
+
re-pairing. Session file previews remain sealed `no-store` HTTP Blob URLs and never enter the application
|
|
138
|
+
cache, IndexedDB, a signed manifest, or a Push payload.
|
|
139
|
+
|
|
140
|
+
Closed-app alerts are opt-in under settings. The server keeps subscriptions only in memory and sends fixed
|
|
141
|
+
generic copy with `TTL: 0` only when the device has no connected cockpit socket. Opening the app after a host
|
|
142
|
+
restart re-registers the browser subscription. Disabling alerts, revoking or expiring the device, switching
|
|
143
|
+
off remote access, or rotating process credentials removes it.
|
|
125
144
|
|
|
126
145
|
## Remote access
|
|
127
146
|
|
|
@@ -137,12 +156,13 @@ so the socket a connection arrived on is the only thing about it that cannot be
|
|
|
137
156
|
|
|
138
157
|
Pairing takes **two** things, not one:
|
|
139
158
|
|
|
140
|
-
1. The host shows a QR encoding `https://<tunnel-host>/pair#c=<code>`.
|
|
141
|
-
fragment, which no browser sends to
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
is
|
|
159
|
+
1. The host shows a QR encoding `https://<tunnel-host>/pair#c=<code>&k=<channel-key>&s=<signer>&r=<revision>`.
|
|
160
|
+
Every value rides in the URL fragment, which no browser sends to a server, so the relay cannot replace the
|
|
161
|
+
channel or bundle key without changing what was shown on the host. Manual pairing requires comparing the
|
|
162
|
+
signing-key fingerprint shown on both devices.
|
|
163
|
+
2. Scanning raises an approve or deny prompt **on the host**. Nothing is paired until someone at the machine
|
|
164
|
+
answers. A screen is visible over a shoulder and in a screenshare, so the code alone is one factor for a
|
|
165
|
+
credential that ends in shell access.
|
|
146
166
|
|
|
147
167
|
A paired device then has the same powers as the person at the keyboard, with one exception: it
|
|
148
168
|
cannot mint pairing codes, approve devices, or change these settings. A device able to approve
|
|
@@ -160,18 +180,24 @@ setting in force at the moment of the check rather than stamped onto a session w
|
|
|
160
180
|
Turning expiry on therefore drops sessions that are already idle, and turning it off brings them
|
|
161
181
|
back.
|
|
162
182
|
|
|
163
|
-
With both off,
|
|
164
|
-
|
|
165
|
-
|
|
183
|
+
With both off, a paired device keeps its session until it is revoked, remote access is switched off, or
|
|
184
|
+
the hub restarts. Switching remote access off always revokes every paired session, and that is not a
|
|
185
|
+
toggle.
|
|
166
186
|
|
|
167
187
|
Before reporting success, the tunnel is **self-tested through its own public URL**: the pairing page
|
|
168
188
|
must answer 200 and `/api/health` must answer 401. Anything else means the agent is on the public
|
|
169
189
|
internet unguarded, so the tunnel is killed immediately rather than warned about.
|
|
170
190
|
|
|
171
|
-
Requires `cloudflared` on `PATH` (`brew install cloudflared`). A quick tunnel needs no account but
|
|
172
|
-
|
|
173
|
-
support SSE on quick tunnels, which breaks
|
|
174
|
-
|
|
191
|
+
Requires `cloudflared` on `PATH` (`brew install cloudflared`). A quick tunnel needs no account but gets a new
|
|
192
|
+
hostname on every start. It does not provide a durable PWA, passkey, or Push identity, and Cloudflare does not
|
|
193
|
+
support SSE on quick tunnels, which breaks workflow and runner-log plugin surfaces. Use a stable named tunnel
|
|
194
|
+
for the Home Screen app.
|
|
195
|
+
|
|
196
|
+
If a named tunnel's connector exits unexpectedly, the hub makes three backoff restart attempts and
|
|
197
|
+
self-tests every replacement. The existing listener and paired sessions stay valid while recovery is
|
|
198
|
+
in progress. A quick tunnel cannot recover transparently because its origin changes, so it still fails
|
|
199
|
+
closed immediately. Exhausting named-tunnel recovery also switches remote access off and revokes the
|
|
200
|
+
paired sessions.
|
|
175
201
|
|
|
176
202
|
### Passkeys and step-up
|
|
177
203
|
|
|
@@ -187,18 +213,20 @@ so rather than letting the ceremony fail in the browser.
|
|
|
187
213
|
|
|
188
214
|
### Tunnel-provider trust and payload privacy
|
|
189
215
|
|
|
190
|
-
Cloudflare
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
216
|
+
Cloudflare terminates TLS and delivers the package-owned pairing and verifier bootstrap. A browser cannot
|
|
217
|
+
independently authenticate that first executable shell against the same edge that served it: a malicious
|
|
218
|
+
replacement could omit the worker and steal a QR fragment. DoomPi does not claim protection from a malicious
|
|
219
|
+
code-delivery edge.
|
|
220
|
+
|
|
221
|
+
After that bootstrap, **bundle signing is mandatory**. The QR pins the host ECDSA key and revision floor. The
|
|
222
|
+
worker verifies the signed manifest plus every raw asset before any host JavaScript executes, serves only the
|
|
223
|
+
atomically committed verified cache, and retains the last-known-good revision on failure. Cloudflare may
|
|
224
|
+
alter the raw bytes, but altered bytes do not execute.
|
|
195
225
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
ciphertext. This limits routine relay visibility, but it still depends on Cloudflare delivering the intended
|
|
201
|
-
pairing page and SPA.
|
|
226
|
+
**The payload is also sealed.** A QR carries an ephemeral P-256 public key in the fragment. A returning
|
|
227
|
+
passkey device restores its channel only after the pinned bundle worker accepts the same signer. Both paths
|
|
228
|
+
complete ECDH and derive separate AES-256-GCM keys per direction. Socket frames and API bodies travel as
|
|
229
|
+
ciphertext.
|
|
202
230
|
|
|
203
231
|
The channel implementation lives in `@agimon-ai/doompi-web-security`, which ships the envelope contract,
|
|
204
232
|
a `node:crypto` half, and a WebCrypto half. **A web plugin that calls `fetch` directly sends plaintext to
|
|
@@ -343,9 +371,9 @@ and the host's own slot contributions) and an optional hub entry (`webHubChannel
|
|
|
343
371
|
dist). This package's own bundle carries no plugins; the full set is assembled on your machine:
|
|
344
372
|
`doompi sync` discovers the installed composition's manifests, generates the import entries, and
|
|
345
373
|
rebuilds the SPA through the `./bundler` subpath into `~/.doompi/web/current`, which the server
|
|
346
|
-
prefers over the packaged bundle (`--assets` and `DOOMPI_WEB_DIST` override it).
|
|
347
|
-
|
|
348
|
-
plugin
|
|
374
|
+
prefers over the packaged bundle (`--assets` and `DOOMPI_WEB_DIST` override it). Server-only
|
|
375
|
+
`webPlugins.server.json` sits beside the public `web/` directory, never inside the signed or served bundle.
|
|
376
|
+
It names each plugin's built hub entry, imported lazily: a missing plugin package logs a notice and its tab
|
|
349
377
|
`@agimon-ai/doompi-team` is the reference plugin; the workflows tab ships with
|
|
350
378
|
`@agimon-ai/doompi-workflow`. Contracts come from `@agimon-ai/doompi-web-contracts`.
|
|
351
379
|
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
6
|
+
<meta name="theme-color" content="#14161a" />
|
|
7
|
+
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
8
|
+
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
9
|
+
<meta name="robots" content="noindex, nofollow" />
|
|
10
|
+
<link rel="manifest" href="/pwa/manifest.webmanifest" />
|
|
11
|
+
<link rel="apple-touch-icon" href="/pwa/icon-192.png" />
|
|
12
|
+
<title>Pair with DoomPi</title>
|
|
13
|
+
<style>
|
|
14
|
+
:root {
|
|
15
|
+
color-scheme: dark;
|
|
16
|
+
}
|
|
17
|
+
* {
|
|
18
|
+
box-sizing: border-box;
|
|
19
|
+
}
|
|
20
|
+
body {
|
|
21
|
+
margin: 0;
|
|
22
|
+
min-height: 100vh;
|
|
23
|
+
min-height: 100dvh;
|
|
24
|
+
display: grid;
|
|
25
|
+
place-items: center;
|
|
26
|
+
padding: max(1.25rem, env(safe-area-inset-top)) max(1.25rem, env(safe-area-inset-right))
|
|
27
|
+
max(1.25rem, env(safe-area-inset-bottom)) max(1.25rem, env(safe-area-inset-left));
|
|
28
|
+
background: #14161a;
|
|
29
|
+
color: #e6e8ec;
|
|
30
|
+
font:
|
|
31
|
+
16px/1.5 ui-sans-serif,
|
|
32
|
+
system-ui,
|
|
33
|
+
-apple-system,
|
|
34
|
+
sans-serif;
|
|
35
|
+
}
|
|
36
|
+
main {
|
|
37
|
+
width: min(32rem, 100%);
|
|
38
|
+
text-align: center;
|
|
39
|
+
}
|
|
40
|
+
h1 {
|
|
41
|
+
margin: 0 0 0.5rem;
|
|
42
|
+
font-size: 1.35rem;
|
|
43
|
+
}
|
|
44
|
+
p {
|
|
45
|
+
margin: 0 0 1rem;
|
|
46
|
+
color: #a2a8b4;
|
|
47
|
+
}
|
|
48
|
+
#pwa-status[data-tone='good'] {
|
|
49
|
+
color: #6bd68a;
|
|
50
|
+
}
|
|
51
|
+
#pwa-status[data-tone='bad'] {
|
|
52
|
+
color: #ff7b7b;
|
|
53
|
+
}
|
|
54
|
+
video {
|
|
55
|
+
width: 100%;
|
|
56
|
+
max-height: 24rem;
|
|
57
|
+
margin: 0.75rem 0;
|
|
58
|
+
border: 1px solid #2c313a;
|
|
59
|
+
border-radius: 0.75rem;
|
|
60
|
+
background: #090a0c;
|
|
61
|
+
object-fit: cover;
|
|
62
|
+
}
|
|
63
|
+
.actions {
|
|
64
|
+
display: flex;
|
|
65
|
+
gap: 0.75rem;
|
|
66
|
+
margin-top: 1.25rem;
|
|
67
|
+
}
|
|
68
|
+
button {
|
|
69
|
+
flex: 1;
|
|
70
|
+
min-height: 3rem;
|
|
71
|
+
border: 1px solid #2f6feb;
|
|
72
|
+
border-radius: 0.6rem;
|
|
73
|
+
background: #2f6feb;
|
|
74
|
+
color: #fff;
|
|
75
|
+
font: inherit;
|
|
76
|
+
font-weight: 650;
|
|
77
|
+
}
|
|
78
|
+
button.secondary {
|
|
79
|
+
border-color: #2c313a;
|
|
80
|
+
background: #1b1e24;
|
|
81
|
+
}
|
|
82
|
+
button:disabled {
|
|
83
|
+
opacity: 0.55;
|
|
84
|
+
}
|
|
85
|
+
[hidden] {
|
|
86
|
+
display: none !important;
|
|
87
|
+
}
|
|
88
|
+
</style>
|
|
89
|
+
<script type="module" crossorigin src="/pwa/pwa.js"></script>
|
|
90
|
+
</head>
|
|
91
|
+
<body data-marker="doompi-pwa-shell">
|
|
92
|
+
<main>
|
|
93
|
+
<h1>Pair this device</h1>
|
|
94
|
+
<p>This cockpit can run shell commands on the host. Pair only with your own DoomPi.</p>
|
|
95
|
+
<p id="pwa-status" role="status">Checking browser support.</p>
|
|
96
|
+
<video id="camera" playsinline muted hidden></video>
|
|
97
|
+
<div class="actions">
|
|
98
|
+
<button id="scan" type="button">Scan pairing QR</button>
|
|
99
|
+
<button id="cancel" class="secondary" type="button" hidden>Cancel</button>
|
|
100
|
+
</div>
|
|
101
|
+
<noscript><p>Pairing needs JavaScript.</p></noscript>
|
|
102
|
+
</main>
|
|
103
|
+
</body>
|
|
104
|
+
</html>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "/pair",
|
|
3
|
+
"name": "DoomPi Cockpit",
|
|
4
|
+
"short_name": "DoomPi",
|
|
5
|
+
"description": "Securely pair with and open your DoomPi cockpit.",
|
|
6
|
+
"start_url": "/",
|
|
7
|
+
"scope": "/",
|
|
8
|
+
"display": "standalone",
|
|
9
|
+
"background_color": "#14161a",
|
|
10
|
+
"theme_color": "#14161a",
|
|
11
|
+
"icons": [
|
|
12
|
+
{
|
|
13
|
+
"src": "/pwa/icon-192.png",
|
|
14
|
+
"sizes": "192x192",
|
|
15
|
+
"type": "image/png"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"src": "/pwa/icon-512.png",
|
|
19
|
+
"sizes": "512x512",
|
|
20
|
+
"type": "image/png"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|