showpane 0.4.14 → 0.4.16
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/bundle/meta/scaffold-manifest.json +8 -8
- package/bundle/scaffold/VERSION +1 -1
- package/bundle/scaffold/prisma/seed.ts +40 -35
- package/bundle/scaffold/src/app/(portal)/client/example/example-client.tsx +1 -2
- package/bundle/scaffold/src/app/(portal)/client/page.tsx +5 -4
- package/bundle/scaffold/src/app/page.tsx +2 -2
- package/bundle/scaffold/src/components/portal-shell.tsx +1 -1
- package/bundle/toolchain/CLI_VERSION +1 -1
- package/bundle/toolchain/VERSION +1 -1
- package/bundle/toolchain/skills/VERSION +1 -1
- package/bundle/toolchain/skills/portal-analytics/SKILL.md +9 -12
- package/bundle/toolchain/skills/portal-analytics/SKILL.md.tmpl +4 -4
- package/bundle/toolchain/skills/portal-create/SKILL.md +13 -16
- package/bundle/toolchain/skills/portal-create/SKILL.md.tmpl +8 -8
- package/bundle/toolchain/skills/portal-credentials/SKILL.md +15 -18
- package/bundle/toolchain/skills/portal-credentials/SKILL.md.tmpl +10 -10
- package/bundle/toolchain/skills/portal-delete/SKILL.md +14 -17
- package/bundle/toolchain/skills/portal-delete/SKILL.md.tmpl +9 -9
- package/bundle/toolchain/skills/portal-deploy/SKILL.md +5 -8
- package/bundle/toolchain/skills/portal-dev/SKILL.md +10 -13
- package/bundle/toolchain/skills/portal-dev/SKILL.md.tmpl +5 -5
- package/bundle/toolchain/skills/portal-list/SKILL.md +15 -18
- package/bundle/toolchain/skills/portal-list/SKILL.md.tmpl +10 -10
- package/bundle/toolchain/skills/portal-onboard/SKILL.md +50 -30
- package/bundle/toolchain/skills/portal-onboard/SKILL.md.tmpl +46 -23
- package/bundle/toolchain/skills/portal-preview/SKILL.md +16 -19
- package/bundle/toolchain/skills/portal-preview/SKILL.md.tmpl +11 -11
- package/bundle/toolchain/skills/portal-setup/SKILL.md +15 -13
- package/bundle/toolchain/skills/portal-setup/SKILL.md.tmpl +11 -6
- package/bundle/toolchain/skills/portal-share/SKILL.md +17 -20
- package/bundle/toolchain/skills/portal-share/SKILL.md.tmpl +12 -12
- package/bundle/toolchain/skills/portal-status/SKILL.md +9 -12
- package/bundle/toolchain/skills/portal-status/SKILL.md.tmpl +4 -4
- package/bundle/toolchain/skills/portal-update/SKILL.md +9 -12
- package/bundle/toolchain/skills/portal-update/SKILL.md.tmpl +4 -4
- package/bundle/toolchain/skills/portal-upgrade/SKILL.md +6 -9
- package/bundle/toolchain/skills/portal-upgrade/SKILL.md.tmpl +1 -1
- package/bundle/toolchain/skills/portal-verify/SKILL.md +6 -9
- package/bundle/toolchain/skills/portal-verify/SKILL.md.tmpl +1 -1
- package/bundle/toolchain/skills/shared/runtime-principles.md +4 -4
- package/bundle/toolchain/templates/sales-followup/sales-followup-client.tsx +1 -1
- package/dist/index.js +28 -5
- package/package.json +3 -3
|
@@ -12,7 +12,7 @@ allowed-tools: [Bash, Read, Write, Edit, Glob, Grep]
|
|
|
12
12
|
|
|
13
13
|
## Overview
|
|
14
14
|
|
|
15
|
-
`/portal
|
|
15
|
+
`/portal-onboard` is the canonical first-run workflow. It should feel like one
|
|
16
16
|
coherent wizard, not like the user is manually hopping between separate skills.
|
|
17
17
|
|
|
18
18
|
The recommended shape is:
|
|
@@ -69,15 +69,14 @@ Start with a compact welcome:
|
|
|
69
69
|
╚══════════════════════════════════════════╝
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
Then
|
|
72
|
+
Then use one short, friendly paragraph. Keep it concise and informal.
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
- first draft
|
|
76
|
-
- local preview
|
|
77
|
-
- access setup
|
|
78
|
-
- cloud publish
|
|
74
|
+
Suggested shape:
|
|
79
75
|
|
|
80
|
-
|
|
76
|
+
- "Let's get your first portal started."
|
|
77
|
+
- "Who's it for, and what's the context? If you've got a call transcript, paste it in and I'll use that too."
|
|
78
|
+
|
|
79
|
+
Keep the opening focused on the user's first portal. This skill is the first-run default, so the top of the flow should feel fast, calm, and immediately useful.
|
|
81
80
|
|
|
82
81
|
Immediately save checkpoint:
|
|
83
82
|
|
|
@@ -97,15 +96,28 @@ If config exists, verify only the minimum first-run requirements before continui
|
|
|
97
96
|
- local SQLite schema is ready
|
|
98
97
|
- org exists or can be created
|
|
99
98
|
|
|
100
|
-
Keep this phase minimal.
|
|
101
|
-
|
|
99
|
+
Keep this phase minimal.
|
|
100
|
+
|
|
101
|
+
If the local checks pass, move straight into the user's portal work without extra system narration.
|
|
102
|
+
|
|
103
|
+
If there is already exactly one local organization and it clearly matches the
|
|
104
|
+
workspace the user just created, treat the org basics as already captured.
|
|
105
|
+
Do not create a separate "company context" phase just to re-ask the same setup
|
|
106
|
+
details.
|
|
107
|
+
|
|
108
|
+
Only ask for a missing field, and ask exactly one thing at a time.
|
|
109
|
+
|
|
110
|
+
Recommended order for missing fields:
|
|
111
|
+
|
|
112
|
+
1. organization name, if it is not already obvious from the workspace setup
|
|
113
|
+
2. contact email
|
|
114
|
+
3. website/domain
|
|
102
115
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
- website/domain if available
|
|
116
|
+
Do not batch these into a numbered questionnaire unless the user explicitly asks
|
|
117
|
+
for the full checklist.
|
|
106
118
|
|
|
107
119
|
Optional extras like brand color, phone number, or contact title belong in
|
|
108
|
-
`/portal
|
|
120
|
+
`/portal-setup` later if needed.
|
|
109
121
|
|
|
110
122
|
If setup fails, stop with a concrete recovery step and keep the checkpoint.
|
|
111
123
|
|
|
@@ -113,9 +125,20 @@ Save checkpoint with phase `local-ready`.
|
|
|
113
125
|
|
|
114
126
|
### Phase 3: Choose the first-portal source
|
|
115
127
|
|
|
116
|
-
|
|
128
|
+
Start with one short source question, not a menu.
|
|
129
|
+
|
|
130
|
+
Recommended opening:
|
|
131
|
+
|
|
132
|
+
- "Who's it for, and what's the context? If you've got a call transcript, paste it in and I'll use that too."
|
|
133
|
+
|
|
134
|
+
Only branch after the user answers:
|
|
135
|
+
|
|
136
|
+
- if they have a real transcript, ask whether to use Granola or paste it
|
|
137
|
+
- if they do not, ask whether they want to start from notes or a template
|
|
138
|
+
|
|
139
|
+
Only show the full menu if the user is unsure:
|
|
117
140
|
|
|
118
|
-
1. recent Granola meeting
|
|
141
|
+
1. recent Granola meeting
|
|
119
142
|
2. pasted transcript
|
|
120
143
|
3. short description of the client + meeting outcome
|
|
121
144
|
4. template-only start
|
|
@@ -160,7 +183,7 @@ Recommended refinement prompts:
|
|
|
160
183
|
- `Do you want the portal to feel more concise, more sales-focused, or more delivery-focused?`
|
|
161
184
|
- `Should we add anything practical before preview — timeline, documents, or sharper next steps?`
|
|
162
185
|
|
|
163
|
-
Apply the requested refinement inline, using the same patterns as `/portal
|
|
186
|
+
Apply the requested refinement inline, using the same patterns as `/portal-update`
|
|
164
187
|
without forcing the user to switch skills.
|
|
165
188
|
|
|
166
189
|
If the user is happy with the first draft, move on immediately.
|
|
@@ -253,8 +276,8 @@ Show a compact final reference card:
|
|
|
253
276
|
Cloud: <hosted-url-or-publishing-status>
|
|
254
277
|
Access: <hosted login / hosted share link / both>
|
|
255
278
|
|
|
256
|
-
Next: /portal
|
|
257
|
-
Help: /portal
|
|
279
|
+
Next: /portal-update <slug>
|
|
280
|
+
Help: /portal-list, /portal-status
|
|
258
281
|
════════════════════════════════════════
|
|
259
282
|
```
|
|
260
283
|
|
|
@@ -309,9 +332,9 @@ to continue refining it or create a new portal. Recommend continuing unless the
|
|
|
309
332
|
- Missing config is not a preamble failure here. It simply means setup starts from scratch.
|
|
310
333
|
- If a step fails after useful progress, keep the checkpoint and tell the user exactly how to resume.
|
|
311
334
|
- If the user wants to stop early, summarize the current state and point them to the next concrete skill:
|
|
312
|
-
- `/portal
|
|
313
|
-
- `/portal
|
|
314
|
-
- `/portal
|
|
315
|
-
- `/portal
|
|
335
|
+
- `/portal-preview`
|
|
336
|
+
- `/portal-credentials`
|
|
337
|
+
- `/portal-share`
|
|
338
|
+
- `/portal-deploy`
|
|
316
339
|
|
|
317
340
|
{{COMPLETION}}
|
|
@@ -15,7 +15,7 @@ SHOWPANE_HOME="$HOME/.showpane"
|
|
|
15
15
|
SHOWPANE_BIN="$SHOWPANE_HOME/bin"
|
|
16
16
|
CONFIG="$SHOWPANE_HOME/config.json"
|
|
17
17
|
if [ ! -f "$CONFIG" ]; then
|
|
18
|
-
echo "Showpane not configured. Run /portal
|
|
18
|
+
echo "Showpane not configured. Run /portal-setup first."
|
|
19
19
|
exit 1
|
|
20
20
|
fi
|
|
21
21
|
|
|
@@ -68,16 +68,13 @@ echo "TEL_PROMPTED: $TEL_PROMPTED"
|
|
|
68
68
|
|
|
69
69
|
If output shows `JUST_UPGRADED <from> <to>`, tell the user Showpane was just upgraded and continue.
|
|
70
70
|
|
|
71
|
-
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal
|
|
71
|
+
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal-upgrade`.
|
|
72
72
|
|
|
73
|
-
If `TEL_PROMPTED` is `no`,
|
|
73
|
+
If `TEL_PROMPTED` is `no`, default telemetry to `anonymous` without interrupting the flow. Do not mention telemetry unless the user asks.
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
- off — local analytics only, no remote sync
|
|
77
|
-
|
|
78
|
-
After the user chooses, run:
|
|
75
|
+
Run:
|
|
79
76
|
```bash
|
|
80
|
-
"$SHOWPANE_BIN/showpane-config" set telemetry
|
|
77
|
+
"$SHOWPANE_BIN/showpane-config" set telemetry anonymous
|
|
81
78
|
touch "$SHOWPANE_HOME/.telemetry-prompted"
|
|
82
79
|
```
|
|
83
80
|
|
|
@@ -109,8 +106,8 @@ If the user specified a slug (e.g., "preview whzan"), use that slug directly.
|
|
|
109
106
|
|
|
110
107
|
If no slug is provided, check how many portals exist:
|
|
111
108
|
- If there is exactly one portal, use that one and mention it: "Opening your only portal: <slug>"
|
|
112
|
-
- If there are multiple portals, ask: "Which portal do you want to preview? Run /portal
|
|
113
|
-
- If there are zero portals, say: "No portals found. Create one first with /portal
|
|
109
|
+
- If there are multiple portals, ask: "Which portal do you want to preview? Run /portal-list to see your portals."
|
|
110
|
+
- If there are zero portals, say: "No portals found. Create one first with /portal-create."
|
|
114
111
|
|
|
115
112
|
For single-portal organizations, auto-selecting saves a round trip.
|
|
116
113
|
|
|
@@ -142,7 +139,7 @@ This handles deployed URLs, custom domains, and any other public preview target.
|
|
|
142
139
|
|
|
143
140
|
If no server is detected and no app URL is configured, do not open the browser. Instead, inform the user:
|
|
144
141
|
|
|
145
|
-
"No running server detected. Start the dev server with /portal
|
|
142
|
+
"No running server detected. Start the dev server with /portal-dev, or set NEXT_PUBLIC_APP_URL in your .env file."
|
|
146
143
|
|
|
147
144
|
### Step 3: Open the URL in the browser
|
|
148
145
|
|
|
@@ -180,7 +177,7 @@ URL: http://localhost:3000/client/<slug>
|
|
|
180
177
|
```
|
|
181
178
|
|
|
182
179
|
If the portal has credentials set up, remind the user:
|
|
183
|
-
"Login with the credentials from /portal
|
|
180
|
+
"Login with the credentials from /portal-credentials <slug>. For external access, publish first with /portal-deploy."
|
|
184
181
|
|
|
185
182
|
If the portal is the example portal (slug is "example"), no credentials are needed -- it is publicly accessible by design.
|
|
186
183
|
|
|
@@ -207,7 +204,7 @@ This order ensures that during development, the user always sees the latest loca
|
|
|
207
204
|
- **Port conflict**: If port 3000 has a non-Showpane process running, `lsof` will still detect it and the URL will be wrong. This is unlikely in practice but worth noting. The user will see a different app in the browser and can correct by specifying the URL manually.
|
|
208
205
|
- **WSL (Windows Subsystem for Linux)**: `xdg-open` may not work. On WSL, use `wslview` or `explorer.exe` instead. Detect WSL via `grep -qi microsoft /proc/version`.
|
|
209
206
|
- **SSH/remote session**: If the user is connected via SSH, opening a browser on the remote machine does nothing useful. Detect this via the `SSH_CONNECTION` environment variable and print the URL instead: "You appear to be in an SSH session. Visit this URL on your local machine: <url>"
|
|
210
|
-
- **Inactive portal**: If the portal is deactivated (`isActive: false`), the preview will show a "not found" page. Warn the user: "Portal '<slug>' is inactive. You'll see a not-found page. Reactivate it first or use /portal
|
|
207
|
+
- **Inactive portal**: If the portal is deactivated (`isActive: false`), the preview will show a "not found" page. Warn the user: "Portal '<slug>' is inactive. You'll see a not-found page. Reactivate it first or use /portal-list to check status."
|
|
211
208
|
|
|
212
209
|
## Error Handling
|
|
213
210
|
|
|
@@ -219,21 +216,21 @@ This order ensures that during development, the user always sees the latest loca
|
|
|
219
216
|
|
|
220
217
|
When the portal opens in the browser, the client will see a login page (unless they have an active session or use a share link). Provide context about how to access the portal:
|
|
221
218
|
|
|
222
|
-
- **Has credentials**: Remind the user of the username (derived from the slug). Do not display the password -- they can get it from `/portal
|
|
223
|
-
- **No credentials**: Warn that the portal will show a login page but there are no credentials to enter. Suggest running `/portal
|
|
219
|
+
- **Has credentials**: Remind the user of the username (derived from the slug). Do not display the password -- they can get it from `/portal-credentials <slug>` if they need it.
|
|
220
|
+
- **No credentials**: Warn that the portal will show a login page but there are no credentials to enter. Suggest running `/portal-credentials <slug>` first.
|
|
224
221
|
- **Example portal**: The built-in example at `/client/example` is publicly accessible and does not require login. No credentials needed.
|
|
225
222
|
|
|
226
|
-
If the user is previewing to check content before sharing with a client, suggest: "To see exactly what the client will see, open an incognito/private window. Your existing session cookies may affect the view. When the portal looks right, publish it with /portal
|
|
223
|
+
If the user is previewing to check content before sharing with a client, suggest: "To see exactly what the client will see, open an incognito/private window. Your existing session cookies may affect the view. When the portal looks right, publish it with /portal-deploy before sending anything externally."
|
|
227
224
|
|
|
228
225
|
## Previewing After Changes
|
|
229
226
|
|
|
230
|
-
A common workflow is: edit portal content with `/portal
|
|
227
|
+
A common workflow is: edit portal content with `/portal-update`, then preview to verify. If the dev server is running with Next.js hot reload, changes to the client component files will appear immediately without a page refresh.
|
|
231
228
|
|
|
232
|
-
If the user just ran `/portal
|
|
229
|
+
If the user just ran `/portal-update` and then `/portal-preview`, mention: "If you don't see your changes, make sure the dev server is running so hot reload can pick them up."
|
|
233
230
|
|
|
234
231
|
## Multiple Portals Preview
|
|
235
232
|
|
|
236
|
-
If the user asks to "preview all portals" or "open all my portals", open each one in a separate browser tab. However, limit to 5 tabs maximum to avoid browser overload. If there are more than 5 portals, open the 5 most recently updated and note: "Opened the 5 most recently updated portals. Use /portal
|
|
233
|
+
If the user asks to "preview all portals" or "open all my portals", open each one in a separate browser tab. However, limit to 5 tabs maximum to avoid browser overload. If there are more than 5 portals, open the 5 most recently updated and note: "Opened the 5 most recently updated portals. Use /portal-preview <slug> for specific portals."
|
|
237
234
|
|
|
238
235
|
To open multiple tabs, run the open command for each URL sequentially:
|
|
239
236
|
|
|
@@ -22,8 +22,8 @@ If the user specified a slug (e.g., "preview whzan"), use that slug directly.
|
|
|
22
22
|
|
|
23
23
|
If no slug is provided, check how many portals exist:
|
|
24
24
|
- If there is exactly one portal, use that one and mention it: "Opening your only portal: <slug>"
|
|
25
|
-
- If there are multiple portals, ask: "Which portal do you want to preview? Run /portal
|
|
26
|
-
- If there are zero portals, say: "No portals found. Create one first with /portal
|
|
25
|
+
- If there are multiple portals, ask: "Which portal do you want to preview? Run /portal-list to see your portals."
|
|
26
|
+
- If there are zero portals, say: "No portals found. Create one first with /portal-create."
|
|
27
27
|
|
|
28
28
|
For single-portal organizations, auto-selecting saves a round trip.
|
|
29
29
|
|
|
@@ -55,7 +55,7 @@ This handles deployed URLs, custom domains, and any other public preview target.
|
|
|
55
55
|
|
|
56
56
|
If no server is detected and no app URL is configured, do not open the browser. Instead, inform the user:
|
|
57
57
|
|
|
58
|
-
"No running server detected. Start the dev server with /portal
|
|
58
|
+
"No running server detected. Start the dev server with /portal-dev, or set NEXT_PUBLIC_APP_URL in your .env file."
|
|
59
59
|
|
|
60
60
|
### Step 3: Open the URL in the browser
|
|
61
61
|
|
|
@@ -93,7 +93,7 @@ URL: http://localhost:3000/client/<slug>
|
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
If the portal has credentials set up, remind the user:
|
|
96
|
-
"Login with the credentials from /portal
|
|
96
|
+
"Login with the credentials from /portal-credentials <slug>. For external access, publish first with /portal-deploy."
|
|
97
97
|
|
|
98
98
|
If the portal is the example portal (slug is "example"), no credentials are needed -- it is publicly accessible by design.
|
|
99
99
|
|
|
@@ -120,7 +120,7 @@ This order ensures that during development, the user always sees the latest loca
|
|
|
120
120
|
- **Port conflict**: If port 3000 has a non-Showpane process running, `lsof` will still detect it and the URL will be wrong. This is unlikely in practice but worth noting. The user will see a different app in the browser and can correct by specifying the URL manually.
|
|
121
121
|
- **WSL (Windows Subsystem for Linux)**: `xdg-open` may not work. On WSL, use `wslview` or `explorer.exe` instead. Detect WSL via `grep -qi microsoft /proc/version`.
|
|
122
122
|
- **SSH/remote session**: If the user is connected via SSH, opening a browser on the remote machine does nothing useful. Detect this via the `SSH_CONNECTION` environment variable and print the URL instead: "You appear to be in an SSH session. Visit this URL on your local machine: <url>"
|
|
123
|
-
- **Inactive portal**: If the portal is deactivated (`isActive: false`), the preview will show a "not found" page. Warn the user: "Portal '<slug>' is inactive. You'll see a not-found page. Reactivate it first or use /portal
|
|
123
|
+
- **Inactive portal**: If the portal is deactivated (`isActive: false`), the preview will show a "not found" page. Warn the user: "Portal '<slug>' is inactive. You'll see a not-found page. Reactivate it first or use /portal-list to check status."
|
|
124
124
|
|
|
125
125
|
## Error Handling
|
|
126
126
|
|
|
@@ -132,21 +132,21 @@ This order ensures that during development, the user always sees the latest loca
|
|
|
132
132
|
|
|
133
133
|
When the portal opens in the browser, the client will see a login page (unless they have an active session or use a share link). Provide context about how to access the portal:
|
|
134
134
|
|
|
135
|
-
- **Has credentials**: Remind the user of the username (derived from the slug). Do not display the password -- they can get it from `/portal
|
|
136
|
-
- **No credentials**: Warn that the portal will show a login page but there are no credentials to enter. Suggest running `/portal
|
|
135
|
+
- **Has credentials**: Remind the user of the username (derived from the slug). Do not display the password -- they can get it from `/portal-credentials <slug>` if they need it.
|
|
136
|
+
- **No credentials**: Warn that the portal will show a login page but there are no credentials to enter. Suggest running `/portal-credentials <slug>` first.
|
|
137
137
|
- **Example portal**: The built-in example at `/client/example` is publicly accessible and does not require login. No credentials needed.
|
|
138
138
|
|
|
139
|
-
If the user is previewing to check content before sharing with a client, suggest: "To see exactly what the client will see, open an incognito/private window. Your existing session cookies may affect the view. When the portal looks right, publish it with /portal
|
|
139
|
+
If the user is previewing to check content before sharing with a client, suggest: "To see exactly what the client will see, open an incognito/private window. Your existing session cookies may affect the view. When the portal looks right, publish it with /portal-deploy before sending anything externally."
|
|
140
140
|
|
|
141
141
|
## Previewing After Changes
|
|
142
142
|
|
|
143
|
-
A common workflow is: edit portal content with `/portal
|
|
143
|
+
A common workflow is: edit portal content with `/portal-update`, then preview to verify. If the dev server is running with Next.js hot reload, changes to the client component files will appear immediately without a page refresh.
|
|
144
144
|
|
|
145
|
-
If the user just ran `/portal
|
|
145
|
+
If the user just ran `/portal-update` and then `/portal-preview`, mention: "If you don't see your changes, make sure the dev server is running so hot reload can pick them up."
|
|
146
146
|
|
|
147
147
|
## Multiple Portals Preview
|
|
148
148
|
|
|
149
|
-
If the user asks to "preview all portals" or "open all my portals", open each one in a separate browser tab. However, limit to 5 tabs maximum to avoid browser overload. If there are more than 5 portals, open the 5 most recently updated and note: "Opened the 5 most recently updated portals. Use /portal
|
|
149
|
+
If the user asks to "preview all portals" or "open all my portals", open each one in a separate browser tab. However, limit to 5 tabs maximum to avoid browser overload. If there are more than 5 portals, open the 5 most recently updated and note: "Opened the 5 most recently updated portals. Use /portal-preview <slug> for specific portals."
|
|
150
150
|
|
|
151
151
|
To open multiple tabs, run the open command for each URL sequentially:
|
|
152
152
|
|
|
@@ -73,16 +73,13 @@ echo "TEL_PROMPTED: $TEL_PROMPTED"
|
|
|
73
73
|
|
|
74
74
|
If output shows `JUST_UPGRADED <from> <to>`, tell the user Showpane was just upgraded and continue.
|
|
75
75
|
|
|
76
|
-
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal
|
|
76
|
+
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal-upgrade`.
|
|
77
77
|
|
|
78
|
-
If `TEL_PROMPTED` is `no`,
|
|
78
|
+
If `TEL_PROMPTED` is `no`, default telemetry to `anonymous` without interrupting the flow. Do not mention telemetry unless the user asks.
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
- off — local analytics only, no remote sync
|
|
82
|
-
|
|
83
|
-
After the user chooses, run:
|
|
80
|
+
Run:
|
|
84
81
|
```bash
|
|
85
|
-
"$SHOWPANE_BIN/showpane-config" set telemetry
|
|
82
|
+
"$SHOWPANE_BIN/showpane-config" set telemetry anonymous
|
|
86
83
|
touch "$SHOWPANE_HOME/.telemetry-prompted"
|
|
87
84
|
```
|
|
88
85
|
|
|
@@ -140,7 +137,7 @@ When the user is inside a freshly generated Showpane project, the setup should:
|
|
|
140
137
|
- Prefer the current working directory as `APP_PATH`
|
|
141
138
|
- Skip any suggestion to clone the upstream Showpane repository
|
|
142
139
|
- Auto-detect SQLite from DATABASE_URL (if it starts with "file:" it's SQLite)
|
|
143
|
-
-
|
|
140
|
+
- Reuse the existing workspace org name if it is already obvious, then ask for the next missing contact detail one at a time
|
|
144
141
|
- Be concise — the user just ran `npx showpane` and wants to get going fast
|
|
145
142
|
|
|
146
143
|
### Step 3: Set the workspace mode
|
|
@@ -190,12 +187,17 @@ Do NOT proceed until the local schema is applied successfully.
|
|
|
190
187
|
|
|
191
188
|
Ask the user for their organization details one at a time. Do not present all questions at once — guide them through the process conversationally.
|
|
192
189
|
|
|
193
|
-
|
|
190
|
+
Before asking anything, check the local database. If there is already exactly one organization and it clearly matches the workspace the user just created, keep it as the default and do not ask for the organization name again unless the user wants to change it.
|
|
191
|
+
|
|
192
|
+
If the org already exists with a real name, ask only for the next missing field.
|
|
193
|
+
Do not restart the whole org questionnaire from the top.
|
|
194
|
+
|
|
195
|
+
1. **Organization name** (required only if not already known) — e.g., "Acme Consulting". This is the name that appears in portal headers alongside the client name.
|
|
194
196
|
2. **Contact name** (required) — the person who appears on portal footers as the point of contact, e.g., "Jane Smith". This is typically the account manager or sales rep.
|
|
195
197
|
3. **Contact email** (required) — e.g., "jane@acme.com". Displayed in the portal footer as a mailto link.
|
|
196
198
|
4. **Contact title** (optional, default: "Account Manager") — e.g., "Director", "Partner", "Client Success Lead". Shown next to the contact name in the portal footer.
|
|
197
199
|
5. **Contact phone** (optional) — e.g., "+44 7700 900000". If provided, displayed alongside email in the portal footer.
|
|
198
|
-
6. **Company website URL**
|
|
200
|
+
6. **Company website URL** — e.g., "acme.com". Ask for it plainly instead of framing it as optional. Used to auto-fetch the company logo via Clearbit.
|
|
199
201
|
- If provided, fetch logo URL: `https://logo.clearbit.com/{domain}` and store in `Organization.logoUrl`
|
|
200
202
|
- Also store the URL in `Organization.websiteUrl`
|
|
201
203
|
7. **Contact avatar**: Auto-populated from the contact email via Gravatar. No need to ask — just use `getAvatarUrl(email, contactName)` from `app/src/lib/branding.ts` and store in `Organization.contactAvatar`
|
|
@@ -227,7 +229,7 @@ Validate the input is a valid hex color:
|
|
|
227
229
|
|
|
228
230
|
Update the Organization record with `primaryColor` set to the validated hex value. The portal app reads this value and applies it via CSS custom properties (the `--primary` variable in the Tailwind theme).
|
|
229
231
|
|
|
230
|
-
If the user says "skip" or "default", use `#1a1a1a`. Brand color can always be changed later by running `/portal
|
|
232
|
+
If the user says "skip" or "default", use `#1a1a1a`. Brand color can always be changed later by running `/portal-setup` again.
|
|
231
233
|
|
|
232
234
|
### Step 8: Telemetry reminder
|
|
233
235
|
|
|
@@ -279,8 +281,8 @@ Showpane setup complete!
|
|
|
279
281
|
Telemetry: anonymous
|
|
280
282
|
|
|
281
283
|
Next steps:
|
|
282
|
-
1. Recommended first run: /portal
|
|
283
|
-
2. Fast repeat-user path: /portal
|
|
284
|
+
1. Recommended first run: /portal-onboard
|
|
285
|
+
2. Fast repeat-user path: /portal-create <slug>
|
|
284
286
|
3. View the example portal: open http://localhost:3000/client/example
|
|
285
287
|
```
|
|
286
288
|
|
|
@@ -54,7 +54,7 @@ When the user is inside a freshly generated Showpane project, the setup should:
|
|
|
54
54
|
- Prefer the current working directory as `APP_PATH`
|
|
55
55
|
- Skip any suggestion to clone the upstream Showpane repository
|
|
56
56
|
- Auto-detect SQLite from DATABASE_URL (if it starts with "file:" it's SQLite)
|
|
57
|
-
-
|
|
57
|
+
- Reuse the existing workspace org name if it is already obvious, then ask for the next missing contact detail one at a time
|
|
58
58
|
- Be concise — the user just ran `npx showpane` and wants to get going fast
|
|
59
59
|
|
|
60
60
|
### Step 3: Set the workspace mode
|
|
@@ -104,12 +104,17 @@ Do NOT proceed until the local schema is applied successfully.
|
|
|
104
104
|
|
|
105
105
|
Ask the user for their organization details one at a time. Do not present all questions at once — guide them through the process conversationally.
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
Before asking anything, check the local database. If there is already exactly one organization and it clearly matches the workspace the user just created, keep it as the default and do not ask for the organization name again unless the user wants to change it.
|
|
108
|
+
|
|
109
|
+
If the org already exists with a real name, ask only for the next missing field.
|
|
110
|
+
Do not restart the whole org questionnaire from the top.
|
|
111
|
+
|
|
112
|
+
1. **Organization name** (required only if not already known) — e.g., "Acme Consulting". This is the name that appears in portal headers alongside the client name.
|
|
108
113
|
2. **Contact name** (required) — the person who appears on portal footers as the point of contact, e.g., "Jane Smith". This is typically the account manager or sales rep.
|
|
109
114
|
3. **Contact email** (required) — e.g., "jane@acme.com". Displayed in the portal footer as a mailto link.
|
|
110
115
|
4. **Contact title** (optional, default: "Account Manager") — e.g., "Director", "Partner", "Client Success Lead". Shown next to the contact name in the portal footer.
|
|
111
116
|
5. **Contact phone** (optional) — e.g., "+44 7700 900000". If provided, displayed alongside email in the portal footer.
|
|
112
|
-
6. **Company website URL**
|
|
117
|
+
6. **Company website URL** — e.g., "acme.com". Ask for it plainly instead of framing it as optional. Used to auto-fetch the company logo via Clearbit.
|
|
113
118
|
- If provided, fetch logo URL: `https://logo.clearbit.com/{domain}` and store in `Organization.logoUrl`
|
|
114
119
|
- Also store the URL in `Organization.websiteUrl`
|
|
115
120
|
7. **Contact avatar**: Auto-populated from the contact email via Gravatar. No need to ask — just use `getAvatarUrl(email, contactName)` from `app/src/lib/branding.ts` and store in `Organization.contactAvatar`
|
|
@@ -141,7 +146,7 @@ Validate the input is a valid hex color:
|
|
|
141
146
|
|
|
142
147
|
Update the Organization record with `primaryColor` set to the validated hex value. The portal app reads this value and applies it via CSS custom properties (the `--primary` variable in the Tailwind theme).
|
|
143
148
|
|
|
144
|
-
If the user says "skip" or "default", use `#1a1a1a`. Brand color can always be changed later by running `/portal
|
|
149
|
+
If the user says "skip" or "default", use `#1a1a1a`. Brand color can always be changed later by running `/portal-setup` again.
|
|
145
150
|
|
|
146
151
|
### Step 8: Telemetry reminder
|
|
147
152
|
|
|
@@ -193,8 +198,8 @@ Showpane setup complete!
|
|
|
193
198
|
Telemetry: anonymous
|
|
194
199
|
|
|
195
200
|
Next steps:
|
|
196
|
-
1. Recommended first run: /portal
|
|
197
|
-
2. Fast repeat-user path: /portal
|
|
201
|
+
1. Recommended first run: /portal-onboard
|
|
202
|
+
2. Fast repeat-user path: /portal-create <slug>
|
|
198
203
|
3. View the example portal: open http://localhost:3000/client/example
|
|
199
204
|
```
|
|
200
205
|
|
|
@@ -18,7 +18,7 @@ SHOWPANE_HOME="$HOME/.showpane"
|
|
|
18
18
|
SHOWPANE_BIN="$SHOWPANE_HOME/bin"
|
|
19
19
|
CONFIG="$SHOWPANE_HOME/config.json"
|
|
20
20
|
if [ ! -f "$CONFIG" ]; then
|
|
21
|
-
echo "Showpane not configured. Run /portal
|
|
21
|
+
echo "Showpane not configured. Run /portal-setup first."
|
|
22
22
|
exit 1
|
|
23
23
|
fi
|
|
24
24
|
|
|
@@ -71,16 +71,13 @@ echo "TEL_PROMPTED: $TEL_PROMPTED"
|
|
|
71
71
|
|
|
72
72
|
If output shows `JUST_UPGRADED <from> <to>`, tell the user Showpane was just upgraded and continue.
|
|
73
73
|
|
|
74
|
-
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal
|
|
74
|
+
If output shows `UPGRADE_AVAILABLE <old> <new>`, tell the user a newer Showpane toolchain is available and recommend `/portal-upgrade`.
|
|
75
75
|
|
|
76
|
-
If `TEL_PROMPTED` is `no`,
|
|
76
|
+
If `TEL_PROMPTED` is `no`, default telemetry to `anonymous` without interrupting the flow. Do not mention telemetry unless the user asks.
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
- off — local analytics only, no remote sync
|
|
80
|
-
|
|
81
|
-
After the user chooses, run:
|
|
78
|
+
Run:
|
|
82
79
|
```bash
|
|
83
|
-
"$SHOWPANE_BIN/showpane-config" set telemetry
|
|
80
|
+
"$SHOWPANE_BIN/showpane-config" set telemetry anonymous
|
|
84
81
|
touch "$SHOWPANE_HOME/.telemetry-prompted"
|
|
85
82
|
```
|
|
86
83
|
|
|
@@ -108,7 +105,7 @@ Share links use HMAC-SHA256 signed tokens. The token encodes the portal slug, a
|
|
|
108
105
|
|
|
109
106
|
### Step 1: Identify the target portal
|
|
110
107
|
|
|
111
|
-
The user must specify which portal to share. If no slug is provided, ask: "Which portal do you want to share? Run /portal
|
|
108
|
+
The user must specify which portal to share. If no slug is provided, ask: "Which portal do you want to share? Run /portal-list to see your portals."
|
|
112
109
|
|
|
113
110
|
Do not proceed without a slug. Share links are portal-specific.
|
|
114
111
|
|
|
@@ -134,8 +131,8 @@ Expected success response:
|
|
|
134
131
|
|
|
135
132
|
Expected error responses:
|
|
136
133
|
|
|
137
|
-
- `portal_not_found`: The slug does not exist. Suggest `/portal
|
|
138
|
-
- `no_credentials`: The portal has no credentials set up. Share links require credentials because the token's validity is tied to the credential version. Suggest running `/portal
|
|
134
|
+
- `portal_not_found`: The slug does not exist. Suggest `/portal-list`.
|
|
135
|
+
- `no_credentials`: The portal has no credentials set up. Share links require credentials because the token's validity is tied to the credential version. Suggest running `/portal-credentials <slug>` first.
|
|
139
136
|
- `no_auth_secret`: AUTH_SECRET is not set in the app's `.env`. The user needs to add one. Suggest: `openssl rand -base64 32` to generate a secret.
|
|
140
137
|
- `no_app_url`: NEXT_PUBLIC_APP_URL is not set. The script cannot construct the full share URL. Ask the user what their portal's public URL is.
|
|
141
138
|
|
|
@@ -164,7 +161,7 @@ If the user has previously generated share links (check learnings for patterns),
|
|
|
164
161
|
Share links are a convenience feature with intentional security trade-offs:
|
|
165
162
|
|
|
166
163
|
- **No automatic expiry**: Links remain valid until credentials are rotated, the portal is deactivated, or AUTH_SECRET changes.
|
|
167
|
-
- **Credential version binding**: Rotating credentials invalidates all outstanding share links. This is the revocation mechanism -- if a link is compromised, rotate credentials with `/portal
|
|
164
|
+
- **Credential version binding**: Rotating credentials invalidates all outstanding share links. This is the revocation mechanism -- if a link is compromised, rotate credentials with `/portal-credentials <slug>`.
|
|
168
165
|
- **Single portal scope**: Each link grants access to exactly one portal. A share link for "whzan" cannot be used to access "acme".
|
|
169
166
|
- **No re-use tracking**: The link can be used multiple times by anyone who has it. There is no per-user tracking on share links.
|
|
170
167
|
|
|
@@ -175,13 +172,13 @@ Do NOT log the share URL to learnings or telemetry. The URL contains the signed
|
|
|
175
172
|
- Always display the full URL, never truncate or abbreviate it. The user needs to copy-paste it.
|
|
176
173
|
- Make it clear that the link does not expire automatically and is revoked by credential rotation or portal deactivation.
|
|
177
174
|
- Use double-line box drawing (`═`) for the border around the link.
|
|
178
|
-
- If NEXT_PUBLIC_APP_URL is `http://localhost:3000`, warn the user immediately: "This is a local development URL. Do not send this to a client. Publish with /portal
|
|
175
|
+
- If NEXT_PUBLIC_APP_URL is `http://localhost:3000`, warn the user immediately: "This is a local development URL. Do not send this to a client. Publish with /portal-deploy first, then generate the share link again."
|
|
179
176
|
|
|
180
177
|
## Error Handling
|
|
181
178
|
|
|
182
179
|
- If AUTH_SECRET is missing, this is a hard blocker. Explain that share links require a signing secret and provide the generation command: `openssl rand -base64 32`.
|
|
183
180
|
- If the portal has no credentials, explain that share links are tied to credential versions and the user needs to set up credentials first.
|
|
184
|
-
- If the script fails for any other reason, show the error message from stderr and suggest the user check their configuration with `/portal
|
|
181
|
+
- If the script fails for any other reason, show the error message from stderr and suggest the user check their configuration with `/portal-status`.
|
|
185
182
|
|
|
186
183
|
## Token Anatomy
|
|
187
184
|
|
|
@@ -214,15 +211,15 @@ The signature is computed using AUTH_SECRET from the app's `.env`. If AUTH_SECRE
|
|
|
214
211
|
|
|
215
212
|
Common patterns for using share links in practice:
|
|
216
213
|
|
|
217
|
-
**After publish**: Deploy the portal with `/portal
|
|
214
|
+
**After publish**: Deploy the portal with `/portal-deploy`, then generate a share link if you want a direct hosted access URL instead of asking the client to log in with credentials.
|
|
218
215
|
|
|
219
216
|
**For quick reviews**: If a colleague or stakeholder needs to see the portal but should not have permanent credentials, a share link is ideal. It can be reused and does not create a full operator login.
|
|
220
217
|
|
|
221
|
-
**Re-sharing after content update**: If you update portal content with `/portal
|
|
218
|
+
**Re-sharing after content update**: If you update portal content with `/portal-update`, publish the latest version if needed, then generate a fresh share link and send it.
|
|
222
219
|
|
|
223
220
|
## Learnings Integration
|
|
224
221
|
|
|
225
|
-
After generating a share link, consider recording a learning entry if this is the first time sharing this portal. The learning helps other skills (like `/portal
|
|
222
|
+
After generating a share link, consider recording a learning entry if this is the first time sharing this portal. The learning helps other skills (like `/portal-analytics`) provide better context:
|
|
226
223
|
|
|
227
224
|
```json
|
|
228
225
|
{"skill":"portal-share","key":"share-event","insight":"whzan shared via link on 2026-04-07","confidence":10,"ts":"2026-04-07T14:30:00Z"}
|
|
@@ -236,15 +233,15 @@ Share links do not expire automatically in this version.
|
|
|
236
233
|
|
|
237
234
|
The revocation mechanisms are:
|
|
238
235
|
|
|
239
|
-
- rotate credentials with `/portal
|
|
240
|
-
- deactivate the portal with `/portal
|
|
236
|
+
- rotate credentials with `/portal-credentials <slug>`
|
|
237
|
+
- deactivate the portal with `/portal-delete <slug>`
|
|
241
238
|
- rotate `AUTH_SECRET`
|
|
242
239
|
|
|
243
240
|
## Multiple Share Links
|
|
244
241
|
|
|
245
242
|
Generating a new share link does not invalidate the previous one. Both links remain valid until credentials are rotated, the portal is deactivated, or AUTH_SECRET changes. This means the user can safely generate multiple links for the same portal (e.g., one for the client contact, one for their colleague) without affecting each other.
|
|
246
243
|
|
|
247
|
-
If the user wants to revoke all outstanding share links immediately, the mechanism is credential rotation: `/portal
|
|
244
|
+
If the user wants to revoke all outstanding share links immediately, the mechanism is credential rotation: `/portal-credentials <slug>`. This bumps the credential version, which invalidates all tokens signed against the previous version.
|
|
248
245
|
|
|
249
246
|
## Completion
|
|
250
247
|
|
|
@@ -21,7 +21,7 @@ Share links use HMAC-SHA256 signed tokens. The token encodes the portal slug, a
|
|
|
21
21
|
|
|
22
22
|
### Step 1: Identify the target portal
|
|
23
23
|
|
|
24
|
-
The user must specify which portal to share. If no slug is provided, ask: "Which portal do you want to share? Run /portal
|
|
24
|
+
The user must specify which portal to share. If no slug is provided, ask: "Which portal do you want to share? Run /portal-list to see your portals."
|
|
25
25
|
|
|
26
26
|
Do not proceed without a slug. Share links are portal-specific.
|
|
27
27
|
|
|
@@ -47,8 +47,8 @@ Expected success response:
|
|
|
47
47
|
|
|
48
48
|
Expected error responses:
|
|
49
49
|
|
|
50
|
-
- `portal_not_found`: The slug does not exist. Suggest `/portal
|
|
51
|
-
- `no_credentials`: The portal has no credentials set up. Share links require credentials because the token's validity is tied to the credential version. Suggest running `/portal
|
|
50
|
+
- `portal_not_found`: The slug does not exist. Suggest `/portal-list`.
|
|
51
|
+
- `no_credentials`: The portal has no credentials set up. Share links require credentials because the token's validity is tied to the credential version. Suggest running `/portal-credentials <slug>` first.
|
|
52
52
|
- `no_auth_secret`: AUTH_SECRET is not set in the app's `.env`. The user needs to add one. Suggest: `openssl rand -base64 32` to generate a secret.
|
|
53
53
|
- `no_app_url`: NEXT_PUBLIC_APP_URL is not set. The script cannot construct the full share URL. Ask the user what their portal's public URL is.
|
|
54
54
|
|
|
@@ -77,7 +77,7 @@ If the user has previously generated share links (check learnings for patterns),
|
|
|
77
77
|
Share links are a convenience feature with intentional security trade-offs:
|
|
78
78
|
|
|
79
79
|
- **No automatic expiry**: Links remain valid until credentials are rotated, the portal is deactivated, or AUTH_SECRET changes.
|
|
80
|
-
- **Credential version binding**: Rotating credentials invalidates all outstanding share links. This is the revocation mechanism -- if a link is compromised, rotate credentials with `/portal
|
|
80
|
+
- **Credential version binding**: Rotating credentials invalidates all outstanding share links. This is the revocation mechanism -- if a link is compromised, rotate credentials with `/portal-credentials <slug>`.
|
|
81
81
|
- **Single portal scope**: Each link grants access to exactly one portal. A share link for "whzan" cannot be used to access "acme".
|
|
82
82
|
- **No re-use tracking**: The link can be used multiple times by anyone who has it. There is no per-user tracking on share links.
|
|
83
83
|
|
|
@@ -88,13 +88,13 @@ Do NOT log the share URL to learnings or telemetry. The URL contains the signed
|
|
|
88
88
|
- Always display the full URL, never truncate or abbreviate it. The user needs to copy-paste it.
|
|
89
89
|
- Make it clear that the link does not expire automatically and is revoked by credential rotation or portal deactivation.
|
|
90
90
|
- Use double-line box drawing (`═`) for the border around the link.
|
|
91
|
-
- If NEXT_PUBLIC_APP_URL is `http://localhost:3000`, warn the user immediately: "This is a local development URL. Do not send this to a client. Publish with /portal
|
|
91
|
+
- If NEXT_PUBLIC_APP_URL is `http://localhost:3000`, warn the user immediately: "This is a local development URL. Do not send this to a client. Publish with /portal-deploy first, then generate the share link again."
|
|
92
92
|
|
|
93
93
|
## Error Handling
|
|
94
94
|
|
|
95
95
|
- If AUTH_SECRET is missing, this is a hard blocker. Explain that share links require a signing secret and provide the generation command: `openssl rand -base64 32`.
|
|
96
96
|
- If the portal has no credentials, explain that share links are tied to credential versions and the user needs to set up credentials first.
|
|
97
|
-
- If the script fails for any other reason, show the error message from stderr and suggest the user check their configuration with `/portal
|
|
97
|
+
- If the script fails for any other reason, show the error message from stderr and suggest the user check their configuration with `/portal-status`.
|
|
98
98
|
|
|
99
99
|
## Token Anatomy
|
|
100
100
|
|
|
@@ -127,15 +127,15 @@ The signature is computed using AUTH_SECRET from the app's `.env`. If AUTH_SECRE
|
|
|
127
127
|
|
|
128
128
|
Common patterns for using share links in practice:
|
|
129
129
|
|
|
130
|
-
**After publish**: Deploy the portal with `/portal
|
|
130
|
+
**After publish**: Deploy the portal with `/portal-deploy`, then generate a share link if you want a direct hosted access URL instead of asking the client to log in with credentials.
|
|
131
131
|
|
|
132
132
|
**For quick reviews**: If a colleague or stakeholder needs to see the portal but should not have permanent credentials, a share link is ideal. It can be reused and does not create a full operator login.
|
|
133
133
|
|
|
134
|
-
**Re-sharing after content update**: If you update portal content with `/portal
|
|
134
|
+
**Re-sharing after content update**: If you update portal content with `/portal-update`, publish the latest version if needed, then generate a fresh share link and send it.
|
|
135
135
|
|
|
136
136
|
## Learnings Integration
|
|
137
137
|
|
|
138
|
-
After generating a share link, consider recording a learning entry if this is the first time sharing this portal. The learning helps other skills (like `/portal
|
|
138
|
+
After generating a share link, consider recording a learning entry if this is the first time sharing this portal. The learning helps other skills (like `/portal-analytics`) provide better context:
|
|
139
139
|
|
|
140
140
|
```json
|
|
141
141
|
{"skill":"portal-share","key":"share-event","insight":"whzan shared via link on 2026-04-07","confidence":10,"ts":"2026-04-07T14:30:00Z"}
|
|
@@ -149,14 +149,14 @@ Share links do not expire automatically in this version.
|
|
|
149
149
|
|
|
150
150
|
The revocation mechanisms are:
|
|
151
151
|
|
|
152
|
-
- rotate credentials with `/portal
|
|
153
|
-
- deactivate the portal with `/portal
|
|
152
|
+
- rotate credentials with `/portal-credentials <slug>`
|
|
153
|
+
- deactivate the portal with `/portal-delete <slug>`
|
|
154
154
|
- rotate `AUTH_SECRET`
|
|
155
155
|
|
|
156
156
|
## Multiple Share Links
|
|
157
157
|
|
|
158
158
|
Generating a new share link does not invalidate the previous one. Both links remain valid until credentials are rotated, the portal is deactivated, or AUTH_SECRET changes. This means the user can safely generate multiple links for the same portal (e.g., one for the client contact, one for their colleague) without affecting each other.
|
|
159
159
|
|
|
160
|
-
If the user wants to revoke all outstanding share links immediately, the mechanism is credential rotation: `/portal
|
|
160
|
+
If the user wants to revoke all outstanding share links immediately, the mechanism is credential rotation: `/portal-credentials <slug>`. This bumps the credential version, which invalidates all tokens signed against the previous version.
|
|
161
161
|
|
|
162
162
|
{{COMPLETION}}
|