@rizom/ops 0.2.0-alpha.13 → 0.2.0-alpha.131

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.
Files changed (36) hide show
  1. package/README.md +4 -1
  2. package/dist/brains-ops.js +263 -160
  3. package/dist/cert-bootstrap.d.ts +1 -1
  4. package/dist/content-repo.d.ts +1 -0
  5. package/dist/deploy.js +3 -170
  6. package/dist/entries/deploy.d.ts +2 -2
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.js +263 -160
  9. package/dist/load-registry.d.ts +13 -2
  10. package/dist/observed-status.d.ts +1 -1
  11. package/dist/origin-ca.d.ts +1 -1
  12. package/dist/parse-args.d.ts +2 -0
  13. package/dist/run-command.d.ts +1 -1
  14. package/dist/schema.d.ts +53 -17
  15. package/dist/secrets-encrypt.d.ts +3 -3
  16. package/dist/secrets-push.d.ts +13 -0
  17. package/dist/ssh-key-bootstrap.d.ts +1 -1
  18. package/dist/user-add.d.ts +15 -0
  19. package/dist/verify-user.d.ts +19 -0
  20. package/package.json +4 -2
  21. package/templates/rover-pilot/.env.schema +17 -3
  22. package/templates/rover-pilot/.github/workflows/build.yml +13 -5
  23. package/templates/rover-pilot/.github/workflows/deploy.yml +31 -10
  24. package/templates/rover-pilot/.github/workflows/reconcile.yml +16 -2
  25. package/templates/rover-pilot/README.md +3 -1
  26. package/templates/rover-pilot/deploy/scripts/decrypt-user-secrets.ts +1 -5
  27. package/templates/rover-pilot/deploy/scripts/resolve-deploy-handles.ts +12 -3
  28. package/templates/rover-pilot/deploy/scripts/update-dns.ts +14 -4
  29. package/templates/rover-pilot/docs/onboarding-checklist.md +32 -12
  30. package/templates/rover-pilot/docs/operator-playbook.md +117 -6
  31. package/templates/rover-pilot/docs/user-onboarding.md +156 -323
  32. package/templates/rover-pilot/pilot.yaml +1 -1
  33. package/templates/rover-pilot/.kamal/hooks/pre-deploy +0 -9
  34. package/templates/rover-pilot/deploy/Caddyfile +0 -72
  35. package/templates/rover-pilot/deploy/Dockerfile +0 -38
  36. package/templates/rover-pilot/deploy/kamal/deploy.yml +0 -40
@@ -1,384 +1,217 @@
1
- # Rover Pilot User Onboarding
1
+ # Welcome to Rover
2
2
 
3
- Welcome to the Rover pilot.
3
+ Rover is your own AI. Not a chatbot you share with the rest of the
4
+ world — a private assistant deployed just for you, that holds your
5
+ notes, links, and ideas, and gets more useful the more you put into
6
+ it.
4
7
 
5
- This document is written for **first-time users**. You do **not** need prior experience with Rover, MCP, git, or the rest of the system to get started.
8
+ This guide walks you through your first days. You don't need
9
+ experience with any particular tools — if you can use a browser, you
10
+ can use Rover.
6
11
 
7
- ## What Rover is
12
+ ## Get in and say hello
8
13
 
9
- Rover is your private AI assistant for working with your own notes, links, and ideas.
14
+ 1. **Open the setup email** we sent you and click the setup link.
15
+ 2. **Register a passkey** — your browser will offer fingerprint,
16
+ face, or PIN. This becomes how you sign in; there is no password.
17
+ 3. **Open your chat**: `https://<handle>.rizom.ai/chat` — sign in
18
+ with the passkey you just made.
19
+ 4. **Say hello.** Ask Rover:
10
20
 
11
- In this pilot, Rover is intentionally simple:
21
+ > What can you help me do?
12
22
 
13
- - you will usually talk to it in **Discord**
14
- - **there is no website to browse**
15
- - **MCP is optional** and only needed for direct client access or specific testing workflows
16
- - your content can also live in a normal git repo of markdown/text files; **Obsidian is optional** if you want a nicer note-editing interface
23
+ That's the whole setup. The chat in your browser is where you and
24
+ Rover will spend most of your time.
17
25
 
18
- You can think of Rover as a private knowledge companion that helps you:
26
+ One caution: the setup link works once and then expires. Don't
27
+ forward it, and if it has already expired when you click it, just
28
+ tell us — we'll send a fresh one.
19
29
 
20
- - save notes
21
- - save links
22
- - reflect on your own material
23
- - find patterns in what you have collected
24
- - think through questions with AI
30
+ ## What your Rover holds
25
31
 
26
- ## What you will receive from us
32
+ Everything in Rover is one of a few simple kinds of things:
27
33
 
28
- We will send you the details you need to get started.
34
+ - **Notes** thoughts, ideas, observations in your own words.
35
+ - **Links** — things from the web, saved with why they matter to you.
36
+ - **Documents** — files you drop into chat: Markdown, PDFs, images.
37
+ - **Topics** — the themes running through your material. You don't
38
+ create these; Rover notices them.
39
+ - **Wishes** — things you asked for that Rover can't do yet.
40
+ - **Agents** — other people's brains, saved to your directory so you
41
+ can ask them things.
29
42
 
30
- That usually includes:
43
+ You'll meet each of these as you go. The first three you put in; the
44
+ last three grow out of how you use it.
31
45
 
32
- - confirmation that Discord is enabled for you, plus the invite/setup steps
33
- - if needed, your Rover MCP URL: `https://<handle>.rizom.ai/mcp`
34
- - if needed, your **Bearer token**
35
- - if needed, an invite to your **private** Rover content repo
36
- - any extra instructions if we are testing a specific workflow with your cohort
46
+ ## The way of working
37
47
 
38
- If we give you a **Bearer token**, treat it like a password. Do not share it.
48
+ Rover is built around a simple loop:
39
49
 
40
- ## One important idea: Discord is the default, MCP is optional
50
+ **Capture ask back shape.**
41
51
 
42
- If you are new to Rover, the shortest explanation is:
52
+ What makes it work: every note, link, and document you hand Rover
53
+ lands in one connected memory. Rover reads what you save, links it
54
+ to what's already there, and notices the topics running through it.
55
+ Nothing sits in a folder waiting to be found — every capture makes
56
+ the next answer better. Ten notes in, Rover is a notebook; a hundred
57
+ notes in, it starts knowing how you think.
43
58
 
44
- - **Rover** is the assistant
45
- - **Discord** is the default way most pilot users will talk to it
46
- - **MCP** is an optional direct connection method for supported AI clients
59
+ The important part is what you _don't_ do: you don't organize. No
60
+ folders, no tags, no filing things in the right place. You throw
61
+ material in as it comes, and Rover makes sense of it when you need
62
+ it.
47
63
 
48
- You do not need to understand the protocol details unless we specifically ask you to use MCP.
64
+ ### Capture
49
65
 
50
- For most users, the practical meaning is simple:
66
+ Notes for what's in your head:
51
67
 
52
- - join Discord
53
- - message Rover there
54
- - start using it
68
+ > Save a note: I keep explaining the same idea to clients — maybe
69
+ > it should be a workshop.
55
70
 
56
- If your cohort is also testing MCP, we will send the URL, Bearer token, and setup help separately.
71
+ Links for what's on your screen:
57
72
 
58
- ## What to use first
73
+ > Save this link with my workshop idea — it's how someone else
74
+ > structures theirs: https://example.com
59
75
 
60
- For most users, the easiest first setup is:
76
+ Documents for what you already have: drop a Markdown file, a PDF, or
77
+ an image into the chat and ask Rover to save or import it. If you
78
+ have notes living somewhere else, this is the fastest way to give
79
+ Rover a head start.
61
80
 
62
- - **Discord** for talking to Rover
63
- - a normal **git repo of markdown/text files** only if you also want to work directly with your content later
64
- - **Obsidian** only if you want a friendlier interface for those same files
65
- - **Claude Desktop** or another MCP client only if we explicitly ask you to test a direct MCP workflow
81
+ ### Ask back
66
82
 
67
- ## Default setup: Discord
83
+ Ask in whatever words occur to you — Rover searches by meaning, not
84
+ exact phrases, so you don't have to remember what you called
85
+ something:
68
86
 
69
- For most users, getting started means:
87
+ > What have I added about the workshop idea?
70
88
 
71
- - join the Discord server we send you
72
- - open the Rover channel or DM
73
- - send a first message
89
+ > What did I save this week?
74
90
 
75
- Try a first message like:
91
+ And as material accumulates, the topics surface — the themes you
92
+ keep returning to without noticing:
76
93
 
77
- > What can you help me do, and what should I use you for?
94
+ > What themes do you see in what I've collected?
78
95
 
79
- Or:
96
+ ### Shape
80
97
 
81
- > Help me save my first note.
98
+ When you want to make something from what you've gathered:
82
99
 
83
- If Discord is not enabled for you yet, tell us and we will share the right next step.
100
+ > Turn my workshop notes into a one-page outline.
84
101
 
85
- ## Optional: direct MCP access
102
+ > Make a reading list from the links I saved.
86
103
 
87
- If we have asked you to use an MCP client, use one that supports:
104
+ Capture is cheap, asking back is instant, and shaping turns a pile
105
+ of fragments into something you can use. That loop is Rover — and it
106
+ only proves itself on real material, so start with things you
107
+ actually want to keep.
88
108
 
89
- - **HTTP / Streamable HTTP MCP**
90
- - **Bearer token authentication**
109
+ ## When Rover can't do something: make a wish
91
110
 
92
- When your client asks for connection details, use:
111
+ Sooner or later you'll ask for something Rover can't do yet. That's
112
+ where wishes come from: Rover says so honestly and offers to save
113
+ the request as a wish:
93
114
 
94
- - **Server URL:** `https://<handle>.rizom.ai/mcp`
95
- - **Authentication type:** Bearer token
96
- - **Bearer token:** the token we sent you
115
+ > I wish you could remind me about this next Monday.
97
116
 
98
- If the client asks for a name, use something simple like:
117
+ Wishes flow back to us and shape what gets built next. Asking for
118
+ things Rover can't do is not a failure — it's one of the most useful
119
+ things a pilot user can do.
99
120
 
100
- - `Rover (<handle>)`
121
+ ## Your Rover in the network
101
122
 
102
- ## Optional: Claude Desktop setup
123
+ The loop has a second payoff. Rover isn't only a private assistant —
124
+ it's your agent in a network of brains, and the connection runs both
125
+ ways.
103
126
 
104
- If we ask you to connect through Claude Desktop and your version supports a **remote HTTP / Streamable HTTP MCP server**, enter:
127
+ **Other people's brains become sources.** When someone you know runs
128
+ a brain, you don't have to send them a message and wait — you ask
129
+ their brain directly, from your own chat. Save it to your agents
130
+ once:
105
131
 
106
- - **Server URL:** `https://<handle>.rizom.ai/mcp`
107
- - **Authentication:** Bearer token
108
- - **Token:** the token we sent you
132
+ > Add yeehaa.io to my agents.
109
133
 
110
- Then try a first message like:
134
+ Then ask questions that put their knowledge next to yours:
111
135
 
112
- > What can you help me do, and what should I use you for?
136
+ > Ask yeehaa.io what they've published about designing workshops,
137
+ > and compare it with my own workshop notes.
113
138
 
114
- Or:
139
+ One ask, both directions: Rover pulls their public knowledge over
140
+ the network, sets it against the material you've been capturing, and
141
+ answers in terms of your situation. What comes back you can think
142
+ with, push back on, or capture:
115
143
 
116
- > Help me save my first note.
144
+ > Save that comparison as a note with my workshop idea.
117
145
 
118
- If your Claude Desktop version only supports local MCP servers and not remote HTTP MCP cleanly, tell us what version you are using and we will help you.
146
+ That's the loop again, with someone else's knowledge feeding your
147
+ capture. Rover never contacts an agent you haven't saved without
148
+ telling you first, and your private material is never shared — only
149
+ the question you send.
119
150
 
120
- ## Your first 5 minutes
151
+ **Your brain becomes a source for others.** The same way you ask
152
+ other agents, they can ask yours. Your Rover answers on your behalf,
153
+ drawing only on what you've chosen to make public — and it builds
154
+ its picture of what you know from everything you capture.
121
155
 
122
- Once you are connected, try this sequence:
156
+ So the network is the quiet consequence of the loop: the more you
157
+ put in, the more useful your Rover is to you — and the better it
158
+ speaks for you when you're not in the room.
123
159
 
124
- ### 1. Check that Rover responds
160
+ ## The other doors
125
161
 
126
- Ask:
162
+ Chat is the primary interface, but your Rover has a few more
163
+ entrances. All optional — ignore them until you're curious:
127
164
 
128
- > What can you help me do?
165
+ - **Dashboard** `https://<handle>.rizom.ai/` is your Rover's home
166
+ page in the browser: a quick overview that everything is running.
167
+ - **CMS** — `https://<handle>.rizom.ai/cms` is a browser editor for
168
+ your content, useful when you want to write or restructure
169
+ something longer than a chat message. If it asks for GitHub
170
+ access, use the instructions we sent; if we didn't send any, skip
171
+ the CMS for now.
172
+ - **Your own AI client (MCP)** — Rover can plug into AI apps you
173
+ already use (Claude, Cursor, and others), signed in with the same
174
+ passkey. If you want this, ask us and we'll send the short setup.
175
+ - **Discord** — available for some pilot cohorts as a secondary
176
+ chat. If it's enabled for you, we'll send the invite separately.
129
177
 
130
- ### 2. Save a first note
178
+ Under the hood, everything you save is plain Markdown in a private
179
+ repository that belongs to you. You never have to touch it — but
180
+ your material is never locked in, either.
131
181
 
132
- Ask:
182
+ ## What to expect from the pilot
133
183
 
134
- > Save a note: I want to use Rover to collect ideas from my work, reading, and conversations.
184
+ This is a real, working system, and an early one. Expect occasional
185
+ rough edges and visible improvement while you use it. Your Rover is
186
+ deployed specifically for you, your content lives in your own
187
+ private store, and sign-in is by passkey. One ask: avoid putting
188
+ highly sensitive material in during the pilot unless we've agreed
189
+ it's in scope — when unsure, ask.
135
190
 
136
- ### 3. Save a useful link
191
+ For questions, feedback, or anything that feels off, join our
192
+ Discord server: `<discord-invite>`. That's the fastest way to reach
193
+ us, and you'll meet the other pilot users there too.
137
194
 
138
- Ask:
195
+ ## If something doesn't work
139
196
 
140
- > Save this link and note why it matters to me: <paste URL>
197
+ - **No setup email** check spam first, then tell us which address
198
+ to use.
199
+ - **Setup link expired** — tell us; we'll reissue it.
200
+ - **Browser asks for a passkey** — expected; use the one you
201
+ registered during setup.
202
+ - **Anything else** — post in the Discord server with the exact
203
+ error text or a screenshot and we'll sort it out. Never paste your
204
+ setup link anywhere except your own browser.
141
205
 
142
- ### 4. Ask Rover to reflect back what it knows
206
+ ## Tell us what you notice
143
207
 
144
- Ask:
208
+ The feedback that helps most is small and honest — drop it in the
209
+ Discord server as it occurs to you:
145
210
 
146
- > Based on what I’ve stored so far, what themes are starting to emerge?
211
+ - where setup confused you
212
+ - what felt useful right away, and what felt pointless
213
+ - what you expected Rover to do that it couldn't
214
+ - whether the capture → ask back → shape loop fits how you work
215
+ - whether you'd keep using Rover after the pilot
147
216
 
148
- ### 5. Use it as a thinking partner
149
-
150
- Ask:
151
-
152
- > I am thinking through a problem in my work. Help me structure the question and identify what context is missing.
153
-
154
- ## Wishlist: when Rover cannot do something yet
155
-
156
- Rover has a built-in **wishlist**.
157
-
158
- This is important for first-time users because Rover will not be able to do everything yet.
159
-
160
- If you ask for something Rover cannot do, it should add that request to the wishlist instead of just failing silently.
161
-
162
- You can think of the wishlist as:
163
-
164
- - a backlog of missing capabilities
165
- - a record of things users want Rover to do
166
- - a way for the pilot team to see which missing features matter most
167
-
168
- ### When the wishlist is useful
169
-
170
- The wishlist is especially useful when you ask Rover to do something like:
171
-
172
- - connect to a tool it does not support yet
173
- - perform an action it cannot perform yet
174
- - add a workflow or feature that does not exist yet
175
-
176
- Examples:
177
-
178
- > I want Rover to draft and send emails for me.
179
-
180
- > I want Rover to connect to my calendar.
181
-
182
- > I want Rover to summarize voice notes automatically.
183
-
184
- If Rover cannot actually do those things yet, it should tell you that and add the request to the wishlist.
185
-
186
- ### What happens when something is added to the wishlist
187
-
188
- When a request is added to the wishlist:
189
-
190
- - it is saved as a **wish**
191
- - it starts in a **new** state
192
- - similar requests can be grouped together instead of creating endless duplicates
193
- - repeated demand can increase the count of how many times that wish was requested
194
-
195
- That helps us see which gaps are one-off ideas and which ones keep coming up across real usage.
196
-
197
- ### How you should use it
198
-
199
- You do **not** need special commands.
200
-
201
- Just ask naturally.
202
-
203
- If Rover cannot do what you asked, a good response from Rover is something like:
204
-
205
- - it explains the limitation clearly
206
- - it says the request was added to the wishlist
207
-
208
- If that does **not** happen, that is useful feedback for us too.
209
-
210
- ## Git, text files, and Obsidian
211
-
212
- The underlying content workflow is a normal **git repo** with normal **markdown/text files**.
213
-
214
- Obsidian is optional. It is just one possible editor for those files.
215
-
216
- That means:
217
-
218
- - use **Discord** as the main way to talk to Rover
219
- - use a normal editor plus **git** if you want to browse, draft, and edit your files directly
220
- - use **Obsidian** only if you want a more note-focused interface for the same files
221
- - Rover can pick up those file changes through the normal git-sync / directory-sync flow
222
-
223
- A simple mental model:
224
-
225
- - **Discord** = talk to Rover
226
- - **git repo + text files** = the underlying content
227
- - **Obsidian** = an optional editor for that content
228
-
229
- ### Important: your content repo is private
230
-
231
- If you use the git/text-file workflow, you will be working in your own **private** GitHub repo.
232
-
233
- That means:
234
-
235
- - you do **not** need repo access just to use Rover in Discord or through MCP
236
- - you **do** need GitHub access if you want to clone, edit, and push to your content repo
237
- - we will invite you only to **your own** content repo, not to the operator repo and not to other users' repos
238
-
239
- ### How you get access
240
-
241
- If you want the git/text-file workflow, we will:
242
-
243
- 1. create or confirm your private content repo
244
- 2. invite your GitHub account to that repo
245
- 3. ask you to accept the GitHub invite
246
- 4. send you the repo URL
247
-
248
- ### Easiest setup for most users
249
-
250
- The easiest path for most first-time users is:
251
-
252
- 1. install **GitHub Desktop**
253
- 2. accept the repo invite in GitHub
254
- 3. clone the private repo with GitHub Desktop
255
- 4. open the cloned folder in your normal editor and edit the markdown/text files directly
256
- 5. optionally open that same folder as an **Obsidian** vault if you prefer
257
- 6. commit and push your changes
258
-
259
- ### Authentication options
260
-
261
- To work with a private repo, you need GitHub authentication.
262
-
263
- Usually the easiest order is:
264
-
265
- 1. **GitHub Desktop** or normal GitHub sign-in
266
- 2. **SSH key** if you already use git that way
267
- 3. a **fine-grained personal access token** only if another tool specifically requires it
268
-
269
- You do **not** need a personal access token just to use Rover in Discord or through MCP.
270
-
271
- If we have already shared your content repo workflow with you, the normal setup is:
272
-
273
- 1. clone your Rover content repo locally
274
- 2. edit the markdown/text files in your normal editor, or open that same folder as an Obsidian vault if you prefer
275
- 3. optionally install the **Obsidian Git** plugin if you want in-app commit/push/pull support
276
- 4. edit or organize your notes there
277
- 5. commit and push your changes through normal git, GitHub Desktop, or the Obsidian Git plugin
278
- 6. let the normal git-sync flow carry those changes into Rover
279
-
280
- If we have **not** given you a direct content repo workflow yet, that is fine. You can ignore git, text files, and Obsidian for now and use Rover in Discord. If we have also asked you to test MCP, you can use that too.
281
-
282
- ## Discord (default)
283
-
284
- Discord is the default interface for this pilot.
285
-
286
- Think of it as the main place to:
287
-
288
- - save quick notes
289
- - drop in links to save
290
- - ask short or long questions
291
- - use Rover day to day without setting up a separate client
292
-
293
- Important:
294
-
295
- - **Discord is the main pilot interface moving forward**
296
- - MCP is **optional**
297
- - if Discord is enabled, we will send the exact invite/setup steps separately
298
- - for some pilot setups, Discord-enabled users may need to supply their own bot token
299
-
300
- If Discord is **not** enabled for you yet, ask us and we will tell you whether your cohort is on the Discord-first workflow.
301
-
302
- ## What to expect in the pilot
303
-
304
- This is a real working system, but it is still an early pilot.
305
-
306
- So you should expect:
307
-
308
- - some rough edges
309
- - a setup process that may still be a bit manual
310
- - a Rover that becomes more useful as you add more notes and links
311
- - occasional follow-up questions from us about your experience
312
- - improvements and changes during the pilot
313
-
314
- That is normal. The point of the pilot is to learn from real use.
315
-
316
- ## Privacy and boundaries
317
-
318
- For the pilot:
319
-
320
- - your Rover is deployed specifically for you
321
- - if you are using MCP, access to `/mcp` is protected by your Bearer token
322
- - you should avoid putting highly sensitive material into the pilot unless we have explicitly agreed that it is in scope
323
-
324
- If you are unsure whether something belongs in Rover, ask us first.
325
-
326
- ## Troubleshooting
327
-
328
- ### I opened the domain and it does not look like a normal site
329
-
330
- That is expected. In this pilot, **there is no website to browse**. Rover runs through Discord and, optionally, a direct MCP endpoint.
331
-
332
- ### I got an authentication error in MCP
333
-
334
- Usually this means one of three things:
335
-
336
- - the Bearer token was missing
337
- - the Bearer token was pasted incorrectly
338
- - the client is using the wrong authentication type
339
-
340
- Double-check that you are using:
341
-
342
- - URL: `https://<handle>.rizom.ai/mcp`
343
- - auth type: **Bearer token**
344
- - token: exactly the token we sent you
345
-
346
- ### My MCP client says it cannot connect
347
-
348
- Some clients support local MCP servers better than remote HTTP MCP servers.
349
-
350
- If that happens, send us:
351
-
352
- - the name of the client
353
- - the version you are using
354
- - the exact error message
355
- - a screenshot if possible
356
-
357
- ## What feedback helps us most
358
-
359
- We especially want to hear:
360
-
361
- - what was confusing during setup
362
- - what felt useful immediately
363
- - what felt weak, awkward, or unclear
364
- - what you expected Rover to do but could not get it to do
365
- - whether you would keep using it after the pilot
366
-
367
- Short, honest feedback is perfect.
368
-
369
- ## Quick handoff template
370
-
371
- When we onboard you, the message will look roughly like this:
372
-
373
- ```text
374
- Discord enabled: yes/no
375
- Discord setup: <invite link or setup steps>
376
- MCP access: optional / enabled / not enabled
377
-
378
- If MCP is enabled:
379
- MCP URL: https://<handle>.rizom.ai/mcp
380
- Auth type: Bearer token
381
- Bearer token: <token>
382
- ```
383
-
384
- If anything is unclear, reply with the exact error text or a screenshot and we will help.
217
+ A few plain sentences are perfect.
@@ -7,5 +7,5 @@ domainSuffix: .rizom.ai
7
7
  preset: core
8
8
  aiApiKey: AI_API_KEY
9
9
  gitSyncToken: GIT_SYNC_TOKEN
10
- mcpAuthToken: MCP_AUTH_TOKEN
10
+ contentRepoAdminToken: CONTENT_REPO_ADMIN_TOKEN
11
11
  agePublicKey: age1replace-with-your-public-key
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- BRAIN_FILE="${BRAIN_YAML_PATH:-brain.yaml}"
5
- SSH_USER="$(ruby -e 'require "yaml"; config = YAML.load_file("deploy/kamal/deploy.yml") || {}; puts(config.dig("ssh", "user") || "root")')"
6
- IFS=',' read -ra HOSTS <<< "$KAMAL_HOSTS"
7
- for host in "${HOSTS[@]}"; do
8
- scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null "$BRAIN_FILE" "${SSH_USER}@${host}:/opt/brain.yaml"
9
- done
@@ -1,72 +0,0 @@
1
- # Internal Caddy — path-based routing to brain services.
2
- # kamal-proxy terminates TLS externally; this runs inside the container.
3
- :80 {
4
- @preview host *-preview.*
5
- handle @preview {
6
- reverse_proxy localhost:4321
7
-
8
- header {
9
- X-Frame-Options "SAMEORIGIN"
10
- X-Content-Type-Options "nosniff"
11
- Referrer-Policy "strict-origin-when-cross-origin"
12
- }
13
- }
14
-
15
- # Health endpoint
16
- handle /health {
17
- reverse_proxy localhost:3333
18
- }
19
-
20
- # MCP endpoint
21
- handle /mcp* {
22
- reverse_proxy localhost:3333
23
-
24
- header {
25
- X-Content-Type-Options "nosniff"
26
- Access-Control-Allow-Origin "*"
27
- Access-Control-Allow-Methods "GET, POST, DELETE, OPTIONS"
28
- Access-Control-Allow-Headers "Content-Type, Authorization, MCP-Session-Id"
29
- }
30
- }
31
-
32
- # A2A endpoints
33
- handle /.well-known/agent-card.json {
34
- reverse_proxy localhost:3334
35
- }
36
-
37
- handle /a2a {
38
- reverse_proxy localhost:3334
39
-
40
- header {
41
- X-Content-Type-Options "nosniff"
42
- Access-Control-Allow-Origin "*"
43
- Access-Control-Allow-Methods "GET, POST, OPTIONS"
44
- Access-Control-Allow-Headers "Content-Type, Authorization"
45
- }
46
- }
47
-
48
- # Plugin API routes
49
- handle /api/* {
50
- reverse_proxy localhost:3335
51
- }
52
-
53
- @root path /
54
- handle @root {
55
- redir /.well-known/agent-card.json 302
56
- }
57
-
58
- # Production site: prefer the webserver when present; otherwise fall back
59
- # to the A2A interface so core-only deployments never return a bare 502.
60
- handle {
61
- reverse_proxy localhost:8080 localhost:3334 {
62
- lb_policy first
63
- lb_retries 1
64
- }
65
-
66
- header {
67
- X-Frame-Options "SAMEORIGIN"
68
- X-Content-Type-Options "nosniff"
69
- Referrer-Policy "strict-origin-when-cross-origin"
70
- }
71
- }
72
- }
@@ -1,38 +0,0 @@
1
- ARG BUN_VERSION=1.3.10
2
- FROM oven/bun:${BUN_VERSION}-slim AS runtime
3
-
4
- WORKDIR /app
5
-
6
- RUN apt-get update && apt-get install -y --no-install-recommends \
7
- curl ca-certificates git gnupg debian-keyring debian-archive-keyring apt-transport-https \
8
- && curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg \
9
- && curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | tee /etc/apt/sources.list.d/caddy-stable.list \
10
- && apt-get update && apt-get install -y --no-install-recommends caddy libcap2-bin \
11
- && setcap cap_net_bind_service=+ep $(which caddy) \
12
- && rm -rf /var/lib/apt/lists/*
13
-
14
- COPY deploy/Caddyfile /etc/caddy/Caddyfile
15
-
16
- RUN mkdir -p /srv/fallback && \
17
- printf '<!doctype html><html><head><meta charset="utf-8"><title>brain</title></head><body></body></html>\n' \
18
- > /srv/fallback/index.html
19
-
20
- ENV XDG_DATA_HOME=/data
21
- ENV XDG_CONFIG_HOME=/config
22
- RUN mkdir -p /app/data /app/cache /app/brain-data && \
23
- chmod -R 777 /app/data /app/cache /app/brain-data
24
-
25
- CMD ["sh", "-c", "caddy start --config /etc/caddy/Caddyfile && exec ./node_modules/.bin/brain start"]
26
-
27
- # --- standalone: bake full project into image (brain-cli deploy) ---
28
- FROM runtime AS standalone
29
- COPY package.json ./package.json
30
- RUN bun install --production --ignore-scripts
31
- COPY . .
32
-
33
- # --- fleet: install published brain at pinned version (ops deploy) ---
34
- FROM runtime AS fleet
35
- ARG BRAIN_VERSION
36
- RUN test -n "$BRAIN_VERSION" \
37
- && printf '{"name":"rover-pilot-runtime","private":true}\n' > package.json \
38
- && bun add @rizom/brain@$BRAIN_VERSION