@henryqw/pi-bark 0.1.2 → 0.1.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # `@henryqw/pi-bark`
2
2
 
3
- Use Bark as an out-of-band status channel for Pi sessions. The extension reports when Pi finishes or waits for input. `/copyb` can also send the last agent message.
3
+ Get [Bark](https://bark.day.app) notifications when Pi finishes or needs your input. Use `/copyb` to send Pi's latest response to your device.
4
4
 
5
5
  ## Install
6
6
 
@@ -84,15 +84,7 @@ These settings do not affect `/copyb`. CWD overrides live in pi-bark's global co
84
84
 
85
85
  ## Flow
86
86
 
87
- ```mermaid
88
- flowchart LR
89
- copy["/copyb"] --> clipboard["Clipboard"]
90
- copy --> bark["pi-bark"]
91
- status["Pi status event"] --> bark
92
- bark --> request["Bark V2 /push request"]
93
- request --> server["Bark server"]
94
- server --> app["Bark App"]
95
- ```
87
+ ![Architecture showing copyb and Pi status notifications entering one shared sender, using AES256-GCM, passing ciphertext through the Bark server, and decrypting locally in the Bark App.](./docs/push-encryption-flow.svg)
96
88
 
97
89
  ## Config
98
90
 
@@ -107,39 +99,55 @@ Package-owned: `~/.pi/agent/config/pi-bark/config.json`
107
99
 
108
100
  ### Push encryption
109
101
 
110
- Push encryption is optional. It prevents the Bark server and Apple Push Notification service from reading the push content.
102
+ Push encryption is optional. It prevents the Bark server and Apple Push Notification service from reading push content.
111
103
 
112
- Generate and store a Custom Encryption Key:
104
+ Once configured, pi-bark encrypts every push it sends. This includes `/copyb` and both automatic status notifications.
113
105
 
114
- ```bash
115
- npx @henryqw/pi-bark
116
- ```
106
+ #### Set up encryption
107
+
108
+ 1. Configure your Bark Device Key with `/set-bark`.
109
+ 2. Generate and save a Custom Encryption Key:
110
+
111
+ ```bash
112
+ npx --yes --package=@henryqw/pi-bark -- pi-bark-key
113
+ ```
117
114
 
118
- The script prints the generated key once. Enter these exact settings in **Bark App Push Encryption**:
115
+ `npx` temporarily downloads the package and runs its `pi-bark-key` executable. The command saves the key to pi-bark's config and prints it once.
119
116
 
120
- | Setting | Value |
121
- | --- | --- |
122
- | Algorithm | `AES256` |
123
- | Mode | `GCM` |
124
- | Padding | `noPadding` |
125
- | Key | The generated 32-character key |
117
+ 3. Open **Bark App → Push Encryption**.
118
+ 4. Enter these settings:
126
119
 
127
- Do not paste script output into shared logs. The Custom Encryption Key can decrypt your push content.
120
+ | Setting | Value |
121
+ | --- | --- |
122
+ | Algorithm | `AES256` |
123
+ | Mode | `GCM` |
124
+ | Padding | `noPadding` |
125
+ | Key | The generated 32-character key |
128
126
 
129
- When enabled, pi-bark encrypts the JSON push content with a fresh 12-character IV. This includes status titles and session names. It sends `device_key`, `ciphertext`, and `iv` to the Bark server.
127
+ The generated ASCII key is 32 characters and 32 bytes.
128
+
129
+ 5. If Bark requires an IV, enter any 12 ASCII characters, such as `000000000000`.
130
+ 6. Save the Bark settings.
131
+ 7. Run `/copyb` in Pi. Bark should show the exact last agent message instead of `Decryption Failed`.
132
+
133
+ The saved IV is only a placeholder for older Bark versions. pi-bark creates a fresh 12-byte IV for each push and sends it with the ciphertext. Bark uses that per-push IV instead of the saved value.
134
+
135
+ Do not paste the command output into shared logs. The Custom Encryption Key can decrypt your push content.
130
136
 
131
137
  The GCM authentication tag is appended to the ciphertext before Base64 encoding, as Bark requires.
132
138
 
133
- The script protects an existing Custom Encryption Key. Replace it only when you intend to update the Bark App too:
139
+ #### Replace or disable the key
140
+
141
+ The command refuses to overwrite an existing key. Replace it only when you also update the Bark App:
134
142
 
135
143
  ```bash
136
- npx @henryqw/pi-bark --force
144
+ npx --yes --package=@henryqw/pi-bark -- pi-bark-key --force
137
145
  ```
138
146
 
139
147
  Disable push encryption in pi-bark with:
140
148
 
141
149
  ```bash
142
- npx @henryqw/pi-bark --disable
150
+ npx --yes --package=@henryqw/pi-bark -- pi-bark-key --disable
143
151
  ```
144
152
 
145
153
  Disable Push Encryption in the Bark App too. Otherwise its settings no longer match pi-bark.
@@ -0,0 +1,166 @@
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.0">
6
+ <title>How pi-bark encrypts every push</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&amp;family=Geist:wght@400;500;600&amp;family=Geist+Mono:wght@400;500;600&amp;display=swap" rel="stylesheet">
8
+ <style>
9
+ *, *::before, *::after { box-sizing: border-box; }
10
+ html, body { margin: 0; min-height: 100%; }
11
+ body { display: grid; place-items: center; background: #f0eee9; }
12
+ figure { margin: 0; width: min(100%, 1280px); }
13
+ svg { display: block; width: 100%; height: auto; }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <figure>
18
+ <svg width="1280" height="720" viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="push-encryption-flow-title push-encryption-flow-desc">
19
+ <title id="push-encryption-flow-title">How pi-bark encrypts every push</title>
20
+ <desc id="push-encryption-flow-desc">Architecture diagram showing copyb messages and automatic Pi status events entering one shared sender. When the config contains a custom key, every push uses AES256-GCM with a fresh 12-byte IV before Bark forwards the ciphertext to the app for local decryption.</desc>
21
+ <defs>
22
+ <style>
23
+ .eyebrow { fill: #4c5665; font: 500 8px 'Geist Mono', monospace; letter-spacing: .16em; }
24
+ .heading { fill: #101828; font: 400 28px 'Instrument Serif', serif; }
25
+ .intro { fill: #4c5665; font: 400 12px 'Geist', sans-serif; }
26
+ .zone { fill: #e6e4de; stroke: #101828; stroke-opacity: .14; stroke-width: 1; }
27
+ .zone-label { fill: #6a7282; font: 500 8px 'Geist Mono', monospace; letter-spacing: .16em; }
28
+ .boundary { fill: none; stroke: #1d4ed8; stroke-opacity: .50; stroke-width: 1; stroke-dasharray: 4 4; }
29
+ .boundary-label { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; letter-spacing: .12em; }
30
+ .node-mask { fill: #f0eee9; }
31
+ .node { fill: #ffffff; stroke: #101828; stroke-width: 1; }
32
+ .node-input { fill: #4c5665; fill-opacity: .10; stroke: #6a7282; stroke-width: 1; }
33
+ .node-store { fill: #101828; fill-opacity: .05; stroke: #4c5665; stroke-width: 1; }
34
+ .node-external { fill: #101828; fill-opacity: .03; stroke: #101828; stroke-opacity: .30; stroke-width: 1; }
35
+ .node-focal { fill: #1d4ed8; fill-opacity: .08; stroke: #1d4ed8; stroke-width: 1.2; }
36
+ .tag { fill: none; stroke: #101828; stroke-opacity: .34; stroke-width: .8; }
37
+ .tag-focal { fill: none; stroke: #1d4ed8; stroke-opacity: .55; stroke-width: .8; }
38
+ .tag-text { fill: #6a7282; font: 500 8px 'Geist Mono', monospace; letter-spacing: .08em; text-anchor: middle; }
39
+ .tag-text-focal { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; letter-spacing: .08em; text-anchor: middle; }
40
+ .name { fill: #101828; font: 600 12px 'Geist', sans-serif; text-anchor: middle; }
41
+ .sub { fill: #4c5665; font: 400 8px 'Geist Mono', monospace; text-anchor: middle; }
42
+ .sub-focal { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; text-anchor: middle; }
43
+ .edge { fill: none; stroke: #4c5665; stroke-width: 1.2; marker-end: url(#push-encryption-arrow); }
44
+ .edge-secure { fill: none; stroke: #1d4ed8; stroke-width: 1.2; marker-end: url(#push-encryption-arrow-accent); }
45
+ .label-mask { fill: #f0eee9; }
46
+ .label { fill: #4c5665; font: 500 8px 'Geist Mono', monospace; letter-spacing: .04em; text-anchor: middle; }
47
+ .label-secure { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; letter-spacing: .04em; text-anchor: middle; }
48
+ .legend-title { fill: #6a7282; font: 500 8px 'Geist Mono', monospace; letter-spacing: .16em; }
49
+ .legend-text { fill: #4c5665; font: 400 8px 'Geist Mono', monospace; }
50
+ </style>
51
+ <marker id="push-encryption-arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
52
+ <polygon points="0 0,8 3,0 6" fill="#4c5665"/>
53
+ </marker>
54
+ <marker id="push-encryption-arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
55
+ <polygon points="0 0,8 3,0 6" fill="#1d4ed8"/>
56
+ </marker>
57
+ <marker id="push-encryption-arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
58
+ <polygon points="0 0,8 3,0 6" fill="#1d4ed8"/>
59
+ </marker>
60
+ </defs>
61
+
62
+ <rect width="1280" height="720" fill="#f0eee9"/>
63
+
64
+ <text class="eyebrow" x="40" y="48">ARCHITECTURE · PI-BARK</text>
65
+ <text class="heading" x="40" y="84">One encryption path for every Bark push</text>
66
+ <text class="intro" x="40" y="112">A configured key applies to manual output and automatic status notifications.</text>
67
+
68
+ <!-- Local trust zone and encrypted transport boundary -->
69
+ <rect class="zone" x="40" y="152" width="816" height="416" rx="8"/>
70
+ <rect class="label-mask" x="52" y="156" width="80" height="16" rx="2"/>
71
+ <text class="zone-label" x="60" y="168">LOCAL PI</text>
72
+
73
+ <line class="boundary" x1="880" y1="176" x2="880" y2="544"/>
74
+ <rect class="label-mask" x="892" y="180" width="240" height="16" rx="2"/>
75
+ <text class="boundary-label" x="900" y="192">CIPHERTEXT LEAVES PI</text>
76
+
77
+ <!-- Connectors are drawn before nodes -->
78
+ <path class="edge" d="M252 248 H292 Q300 248 300 256 V308 Q300 316 308 316 H352"/>
79
+ <path class="edge" d="M252 400 H304 Q312 400 312 392 V372 Q312 364 320 364 H352"/>
80
+ <line class="edge" x1="452" y1="452" x2="452" y2="396"/>
81
+ <line class="edge-secure" x1="552" y1="340" x2="648" y2="340"/>
82
+ <line class="edge-secure" x1="848" y1="340" x2="920" y2="340"/>
83
+ <line class="edge-secure" x1="1060" y1="340" x2="1100" y2="340"/>
84
+
85
+ <!-- Connector labels -->
86
+ <rect class="label-mask" x="464" y="416" width="72" height="12" rx="2"/>
87
+ <text class="label" x="500" y="424">LOAD EACH PUSH</text>
88
+
89
+ <rect class="label-mask" x="568" y="320" width="64" height="12" rx="2"/>
90
+ <text class="label-secure" x="600" y="328">KEY PRESENT</text>
91
+
92
+ <rect class="label-mask" x="856" y="320" width="56" height="12" rx="2"/>
93
+ <text class="label-secure" x="884" y="328">POST /PUSH</text>
94
+
95
+ <!-- Opaque node masks -->
96
+ <rect class="node-mask" x="72" y="208" width="180" height="80" rx="6"/>
97
+ <rect class="node-mask" x="72" y="360" width="180" height="80" rx="6"/>
98
+ <rect class="node-mask" x="352" y="284" width="200" height="112" rx="6"/>
99
+ <rect class="node-mask" x="352" y="452" width="200" height="80" rx="6"/>
100
+ <rect class="node-mask" x="648" y="284" width="200" height="112" rx="6"/>
101
+ <rect class="node-mask" x="920" y="284" width="140" height="112" rx="6"/>
102
+ <rect class="node-mask" x="1100" y="284" width="140" height="112" rx="6"/>
103
+
104
+ <!-- Inputs -->
105
+ <rect class="node-input" x="72" y="208" width="180" height="80" rx="6"/>
106
+ <rect class="tag" x="84" y="220" width="56" height="16" rx="2"/>
107
+ <text class="tag-text" x="112" y="232">COMMAND</text>
108
+ <text class="name" x="162" y="256">/copyb</text>
109
+ <text class="sub" x="162" y="276">LAST AGENT MESSAGE</text>
110
+
111
+ <rect class="node-input" x="72" y="360" width="180" height="80" rx="6"/>
112
+ <rect class="tag" x="84" y="372" width="48" height="16" rx="2"/>
113
+ <text class="tag-text" x="108" y="384">EVENT</text>
114
+ <text class="name" x="162" y="408">Pi status</text>
115
+ <text class="sub" x="162" y="428">NEEDS INPUT · FINISHED</text>
116
+
117
+ <!-- Shared sender and config -->
118
+ <rect class="node" x="352" y="284" width="200" height="112" rx="6"/>
119
+ <rect class="tag" x="364" y="296" width="48" height="16" rx="2"/>
120
+ <text class="tag-text" x="388" y="308">SHARED</text>
121
+ <text class="name" x="452" y="340">Push sender</text>
122
+ <text class="sub" x="452" y="364">ONE PATH FOR EVERY PUSH</text>
123
+ <text class="sub" x="452" y="380">DEVICE KEY + CONTENT</text>
124
+
125
+ <rect class="node-store" x="352" y="452" width="200" height="80" rx="6"/>
126
+ <rect class="tag" x="364" y="464" width="48" height="16" rx="2"/>
127
+ <text class="tag-text" x="388" y="476">CONFIG</text>
128
+ <text class="name" x="452" y="500">pi-bark config</text>
129
+ <text class="sub" x="452" y="520">DEVICE KEY · CUSTOM KEY</text>
130
+
131
+ <!-- Encryption focal point -->
132
+ <rect class="node-focal" x="648" y="284" width="200" height="112" rx="6"/>
133
+ <rect class="tag-focal" x="660" y="296" width="56" height="16" rx="2"/>
134
+ <text class="tag-text-focal" x="688" y="308">ENCRYPT</text>
135
+ <text class="name" x="748" y="340">AES256-GCM</text>
136
+ <text class="sub-focal" x="748" y="364">FRESH 12-BYTE IV</text>
137
+ <text class="sub-focal" x="748" y="380">AUTH TAG APPENDED</text>
138
+
139
+ <!-- External delivery -->
140
+ <rect class="node-external" x="920" y="284" width="140" height="112" rx="6"/>
141
+ <rect class="tag" x="932" y="296" width="48" height="16" rx="2"/>
142
+ <text class="tag-text" x="956" y="308">SERVER</text>
143
+ <text class="name" x="990" y="340">Bark server</text>
144
+ <text class="sub" x="990" y="364">FORWARDS ONLY</text>
145
+ <text class="sub" x="990" y="380">CANNOT READ CONTENT</text>
146
+
147
+ <rect class="node" x="1100" y="284" width="140" height="112" rx="6"/>
148
+ <rect class="tag" x="1112" y="296" width="32" height="16" rx="2"/>
149
+ <text class="tag-text" x="1128" y="308">APP</text>
150
+ <text class="name" x="1170" y="340">Bark App</text>
151
+ <text class="sub" x="1170" y="364">MATCHING 32-BYTE KEY</text>
152
+ <text class="sub" x="1170" y="380">DECRYPTS LOCALLY</text>
153
+
154
+ <!-- Legend -->
155
+ <line x1="40" y1="616" x2="1240" y2="616" stroke="#101828" stroke-opacity=".14" stroke-width=".8"/>
156
+ <text class="legend-title" x="40" y="652">LEGEND</text>
157
+ <line x1="144" y1="648" x2="184" y2="648" stroke="#4c5665" stroke-width="1.2" marker-end="url(#push-encryption-arrow)"/>
158
+ <text class="legend-text" x="196" y="652">LOCAL CONTENT</text>
159
+ <line x1="344" y1="648" x2="384" y2="648" stroke="#1d4ed8" stroke-width="1.2" marker-end="url(#push-encryption-arrow-accent)"/>
160
+ <text class="legend-text" x="396" y="652">ENCRYPTED CONTENT</text>
161
+ <rect x="568" y="640" width="16" height="16" rx="4" fill="#1d4ed8" fill-opacity=".08" stroke="#1d4ed8" stroke-width="1"/>
162
+ <text class="legend-text" x="596" y="652">ENCRYPTION BOUNDARY</text>
163
+ </svg>
164
+ </figure>
165
+ </body>
166
+ </html>
@@ -0,0 +1,148 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="1280" height="720" viewBox="0 0 1280 720" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="push-encryption-flow-title push-encryption-flow-desc">
3
+ <title id="push-encryption-flow-title">How pi-bark encrypts every push</title>
4
+ <desc id="push-encryption-flow-desc">Architecture diagram showing copyb messages and automatic Pi status events entering one shared sender. When the config contains a custom key, every push uses AES256-GCM with a fresh 12-byte IV before Bark forwards the ciphertext to the app for local decryption.</desc>
5
+ <defs>
6
+ <style>@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&amp;family=Geist:wght@400;500;600&amp;family=Geist+Mono:wght@400;500;600&amp;display=swap');</style>
7
+ <style>
8
+ .eyebrow { fill: #4c5665; font: 500 8px 'Geist Mono', monospace; letter-spacing: .16em; }
9
+ .heading { fill: #101828; font: 400 28px 'Instrument Serif', serif; }
10
+ .intro { fill: #4c5665; font: 400 12px 'Geist', sans-serif; }
11
+ .zone { fill: #e6e4de; stroke: #101828; stroke-opacity: .14; stroke-width: 1; }
12
+ .zone-label { fill: #6a7282; font: 500 8px 'Geist Mono', monospace; letter-spacing: .16em; }
13
+ .boundary { fill: none; stroke: #1d4ed8; stroke-opacity: .50; stroke-width: 1; stroke-dasharray: 4 4; }
14
+ .boundary-label { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; letter-spacing: .12em; }
15
+ .node-mask { fill: #f0eee9; }
16
+ .node { fill: #ffffff; stroke: #101828; stroke-width: 1; }
17
+ .node-input { fill: #4c5665; fill-opacity: .10; stroke: #6a7282; stroke-width: 1; }
18
+ .node-store { fill: #101828; fill-opacity: .05; stroke: #4c5665; stroke-width: 1; }
19
+ .node-external { fill: #101828; fill-opacity: .03; stroke: #101828; stroke-opacity: .30; stroke-width: 1; }
20
+ .node-focal { fill: #1d4ed8; fill-opacity: .08; stroke: #1d4ed8; stroke-width: 1.2; }
21
+ .tag { fill: none; stroke: #101828; stroke-opacity: .34; stroke-width: .8; }
22
+ .tag-focal { fill: none; stroke: #1d4ed8; stroke-opacity: .55; stroke-width: .8; }
23
+ .tag-text { fill: #6a7282; font: 500 8px 'Geist Mono', monospace; letter-spacing: .08em; text-anchor: middle; }
24
+ .tag-text-focal { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; letter-spacing: .08em; text-anchor: middle; }
25
+ .name { fill: #101828; font: 600 12px 'Geist', sans-serif; text-anchor: middle; }
26
+ .sub { fill: #4c5665; font: 400 8px 'Geist Mono', monospace; text-anchor: middle; }
27
+ .sub-focal { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; text-anchor: middle; }
28
+ .edge { fill: none; stroke: #4c5665; stroke-width: 1.2; marker-end: url(#push-encryption-arrow); }
29
+ .edge-secure { fill: none; stroke: #1d4ed8; stroke-width: 1.2; marker-end: url(#push-encryption-arrow-accent); }
30
+ .label-mask { fill: #f0eee9; }
31
+ .label { fill: #4c5665; font: 500 8px 'Geist Mono', monospace; letter-spacing: .04em; text-anchor: middle; }
32
+ .label-secure { fill: #1d4ed8; font: 500 8px 'Geist Mono', monospace; letter-spacing: .04em; text-anchor: middle; }
33
+ .legend-title { fill: #6a7282; font: 500 8px 'Geist Mono', monospace; letter-spacing: .16em; }
34
+ .legend-text { fill: #4c5665; font: 400 8px 'Geist Mono', monospace; }
35
+ </style>
36
+ <marker id="push-encryption-arrow" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
37
+ <polygon points="0 0,8 3,0 6" fill="#4c5665"/>
38
+ </marker>
39
+ <marker id="push-encryption-arrow-accent" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
40
+ <polygon points="0 0,8 3,0 6" fill="#1d4ed8"/>
41
+ </marker>
42
+ <marker id="push-encryption-arrow-link" markerWidth="8" markerHeight="6" refX="7" refY="3" orient="auto">
43
+ <polygon points="0 0,8 3,0 6" fill="#1d4ed8"/>
44
+ </marker>
45
+ </defs>
46
+
47
+ <rect width="1280" height="720" fill="#f0eee9"/>
48
+
49
+ <text class="eyebrow" x="40" y="48">ARCHITECTURE · PI-BARK</text>
50
+ <text class="heading" x="40" y="84">One encryption path for every Bark push</text>
51
+ <text class="intro" x="40" y="112">A configured key applies to manual output and automatic status notifications.</text>
52
+
53
+ <!-- Local trust zone and encrypted transport boundary -->
54
+ <rect class="zone" x="40" y="152" width="816" height="416" rx="8"/>
55
+ <rect class="label-mask" x="52" y="156" width="80" height="16" rx="2"/>
56
+ <text class="zone-label" x="60" y="168">LOCAL PI</text>
57
+
58
+ <line class="boundary" x1="880" y1="176" x2="880" y2="544"/>
59
+ <rect class="label-mask" x="892" y="180" width="240" height="16" rx="2"/>
60
+ <text class="boundary-label" x="900" y="192">CIPHERTEXT LEAVES PI</text>
61
+
62
+ <!-- Connectors are drawn before nodes -->
63
+ <path class="edge" d="M252 248 H292 Q300 248 300 256 V308 Q300 316 308 316 H352"/>
64
+ <path class="edge" d="M252 400 H304 Q312 400 312 392 V372 Q312 364 320 364 H352"/>
65
+ <line class="edge" x1="452" y1="452" x2="452" y2="396"/>
66
+ <line class="edge-secure" x1="552" y1="340" x2="648" y2="340"/>
67
+ <line class="edge-secure" x1="848" y1="340" x2="920" y2="340"/>
68
+ <line class="edge-secure" x1="1060" y1="340" x2="1100" y2="340"/>
69
+
70
+ <!-- Connector labels -->
71
+ <rect class="label-mask" x="464" y="416" width="72" height="12" rx="2"/>
72
+ <text class="label" x="500" y="424">LOAD EACH PUSH</text>
73
+
74
+ <rect class="label-mask" x="568" y="320" width="64" height="12" rx="2"/>
75
+ <text class="label-secure" x="600" y="328">KEY PRESENT</text>
76
+
77
+ <rect class="label-mask" x="856" y="320" width="56" height="12" rx="2"/>
78
+ <text class="label-secure" x="884" y="328">POST /PUSH</text>
79
+
80
+ <!-- Opaque node masks -->
81
+ <rect class="node-mask" x="72" y="208" width="180" height="80" rx="6"/>
82
+ <rect class="node-mask" x="72" y="360" width="180" height="80" rx="6"/>
83
+ <rect class="node-mask" x="352" y="284" width="200" height="112" rx="6"/>
84
+ <rect class="node-mask" x="352" y="452" width="200" height="80" rx="6"/>
85
+ <rect class="node-mask" x="648" y="284" width="200" height="112" rx="6"/>
86
+ <rect class="node-mask" x="920" y="284" width="140" height="112" rx="6"/>
87
+ <rect class="node-mask" x="1100" y="284" width="140" height="112" rx="6"/>
88
+
89
+ <!-- Inputs -->
90
+ <rect class="node-input" x="72" y="208" width="180" height="80" rx="6"/>
91
+ <rect class="tag" x="84" y="220" width="56" height="16" rx="2"/>
92
+ <text class="tag-text" x="112" y="232">COMMAND</text>
93
+ <text class="name" x="162" y="256">/copyb</text>
94
+ <text class="sub" x="162" y="276">LAST AGENT MESSAGE</text>
95
+
96
+ <rect class="node-input" x="72" y="360" width="180" height="80" rx="6"/>
97
+ <rect class="tag" x="84" y="372" width="48" height="16" rx="2"/>
98
+ <text class="tag-text" x="108" y="384">EVENT</text>
99
+ <text class="name" x="162" y="408">Pi status</text>
100
+ <text class="sub" x="162" y="428">NEEDS INPUT · FINISHED</text>
101
+
102
+ <!-- Shared sender and config -->
103
+ <rect class="node" x="352" y="284" width="200" height="112" rx="6"/>
104
+ <rect class="tag" x="364" y="296" width="48" height="16" rx="2"/>
105
+ <text class="tag-text" x="388" y="308">SHARED</text>
106
+ <text class="name" x="452" y="340">Push sender</text>
107
+ <text class="sub" x="452" y="364">ONE PATH FOR EVERY PUSH</text>
108
+ <text class="sub" x="452" y="380">DEVICE KEY + CONTENT</text>
109
+
110
+ <rect class="node-store" x="352" y="452" width="200" height="80" rx="6"/>
111
+ <rect class="tag" x="364" y="464" width="48" height="16" rx="2"/>
112
+ <text class="tag-text" x="388" y="476">CONFIG</text>
113
+ <text class="name" x="452" y="500">pi-bark config</text>
114
+ <text class="sub" x="452" y="520">DEVICE KEY · CUSTOM KEY</text>
115
+
116
+ <!-- Encryption focal point -->
117
+ <rect class="node-focal" x="648" y="284" width="200" height="112" rx="6"/>
118
+ <rect class="tag-focal" x="660" y="296" width="56" height="16" rx="2"/>
119
+ <text class="tag-text-focal" x="688" y="308">ENCRYPT</text>
120
+ <text class="name" x="748" y="340">AES256-GCM</text>
121
+ <text class="sub-focal" x="748" y="364">FRESH 12-BYTE IV</text>
122
+ <text class="sub-focal" x="748" y="380">AUTH TAG APPENDED</text>
123
+
124
+ <!-- External delivery -->
125
+ <rect class="node-external" x="920" y="284" width="140" height="112" rx="6"/>
126
+ <rect class="tag" x="932" y="296" width="48" height="16" rx="2"/>
127
+ <text class="tag-text" x="956" y="308">SERVER</text>
128
+ <text class="name" x="990" y="340">Bark server</text>
129
+ <text class="sub" x="990" y="364">FORWARDS ONLY</text>
130
+ <text class="sub" x="990" y="380">CANNOT READ CONTENT</text>
131
+
132
+ <rect class="node" x="1100" y="284" width="140" height="112" rx="6"/>
133
+ <rect class="tag" x="1112" y="296" width="32" height="16" rx="2"/>
134
+ <text class="tag-text" x="1128" y="308">APP</text>
135
+ <text class="name" x="1170" y="340">Bark App</text>
136
+ <text class="sub" x="1170" y="364">MATCHING 32-BYTE KEY</text>
137
+ <text class="sub" x="1170" y="380">DECRYPTS LOCALLY</text>
138
+
139
+ <!-- Legend -->
140
+ <line x1="40" y1="616" x2="1240" y2="616" stroke="#101828" stroke-opacity=".14" stroke-width=".8"/>
141
+ <text class="legend-title" x="40" y="652">LEGEND</text>
142
+ <line x1="144" y1="648" x2="184" y2="648" stroke="#4c5665" stroke-width="1.2" marker-end="url(#push-encryption-arrow)"/>
143
+ <text class="legend-text" x="196" y="652">LOCAL CONTENT</text>
144
+ <line x1="344" y1="648" x2="384" y2="648" stroke="#1d4ed8" stroke-width="1.2" marker-end="url(#push-encryption-arrow-accent)"/>
145
+ <text class="legend-text" x="396" y="652">ENCRYPTED CONTENT</text>
146
+ <rect x="568" y="640" width="16" height="16" rx="4" fill="#1d4ed8" fill-opacity=".08" stroke="#1d4ed8" stroke-width="1"/>
147
+ <text class="legend-text" x="596" y="652">ENCRYPTION BOUNDARY</text>
148
+ </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@henryqw/pi-bark",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Send Pi session status and agent output to Bark on iOS.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -17,6 +17,7 @@
17
17
  "files": [
18
18
  "LICENSE",
19
19
  "dist",
20
+ "docs",
20
21
  "extensions",
21
22
  "scripts",
22
23
  "src",