@miakapp/cli 4.0.0-alpha.0 → 4.0.0-alpha.10

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 (63) hide show
  1. package/README.md +151 -35
  2. package/assets/agent-guide.md +232 -79
  3. package/assets/design/OFL-Manrope.txt +93 -0
  4. package/assets/design/components.css +139 -0
  5. package/assets/design/fonts.css +9 -0
  6. package/assets/design/gallery.html +667 -0
  7. package/assets/design/guide.md +77 -0
  8. package/assets/design/tokens.css +185 -0
  9. package/assets/starter/app/app/README.md +74 -0
  10. package/assets/starter/app/app/main.ts +124 -0
  11. package/assets/starter/app/app/miakapp.ts +156 -0
  12. package/assets/starter/app/app/theme.ts +8 -0
  13. package/assets/starter/app/tsconfig.json +23 -0
  14. package/bin/miakapp.js +5 -1
  15. package/dist/agent-pack.d.ts +11 -3
  16. package/dist/agent-pack.d.ts.map +1 -1
  17. package/dist/agent-pack.js +26 -10
  18. package/dist/agent-pack.js.map +1 -1
  19. package/dist/contexts.d.ts +59 -0
  20. package/dist/contexts.d.ts.map +1 -0
  21. package/dist/contexts.js +388 -0
  22. package/dist/contexts.js.map +1 -0
  23. package/dist/control-plane.d.ts +14 -0
  24. package/dist/control-plane.d.ts.map +1 -1
  25. package/dist/control-plane.js +33 -1
  26. package/dist/control-plane.js.map +1 -1
  27. package/dist/internal/names.d.ts +5 -0
  28. package/dist/internal/names.d.ts.map +1 -1
  29. package/dist/internal/names.js +6 -0
  30. package/dist/internal/names.js.map +1 -1
  31. package/dist/main.d.ts +22 -5
  32. package/dist/main.d.ts.map +1 -1
  33. package/dist/main.js +673 -60
  34. package/dist/main.js.map +1 -1
  35. package/dist/mcp.d.ts +7 -1
  36. package/dist/mcp.d.ts.map +1 -1
  37. package/dist/mcp.js +195 -26
  38. package/dist/mcp.js.map +1 -1
  39. package/dist/pairing.d.ts +27 -0
  40. package/dist/pairing.d.ts.map +1 -0
  41. package/dist/pairing.js +148 -0
  42. package/dist/pairing.js.map +1 -0
  43. package/dist/project.d.ts +3 -1
  44. package/dist/project.d.ts.map +1 -1
  45. package/dist/project.js +33 -6
  46. package/dist/project.js.map +1 -1
  47. package/dist/publication.d.ts +20 -5
  48. package/dist/publication.d.ts.map +1 -1
  49. package/dist/publication.js +58 -16
  50. package/dist/publication.js.map +1 -1
  51. package/dist/starter.d.ts +17 -0
  52. package/dist/starter.d.ts.map +1 -0
  53. package/dist/starter.js +72 -0
  54. package/dist/starter.js.map +1 -0
  55. package/dist/terminal.d.ts +10 -0
  56. package/dist/terminal.d.ts.map +1 -0
  57. package/dist/terminal.js +70 -0
  58. package/dist/terminal.js.map +1 -0
  59. package/dist/version.d.ts +15 -0
  60. package/dist/version.d.ts.map +1 -0
  61. package/dist/version.js +15 -0
  62. package/dist/version.js.map +1 -0
  63. package/package.json +6 -4
@@ -10,6 +10,44 @@ Everything below is true of the code in this repository. Where a rule exists for
10
10
  a reason that is not obvious, the reason is given, because a rule whose purpose
11
11
  you cannot see is one you will optimize away.
12
12
 
13
+ ## 0. What "done" means
14
+
15
+ The owner asked for a home they can use, not for a picture of one. You are done
16
+ when the household can open the published interface, read real values from it
17
+ and use every control the owner authorized — and you checked that yourself.
18
+ Concretely:
19
+
20
+ - **Publish, then verify.** A build that only runs on your machine, a mockup, a
21
+ prototype kept offline or a screenshot is an intermediate result, never the
22
+ deliverable. Do not stop to show one and ask whether to continue: the owner
23
+ asked for the home, and publication is reversible in one command (§8).
24
+ - **Hand over a link that works.** Give the owner the `home_url` that
25
+ `miakapp publish` and `miakapp status` print — the Miakapp address where the
26
+ home opens for its members — and say what you verified there. The
27
+ `artifact_url` (JSON `url`) is the raw bundle, not an interface: never send it
28
+ as "the link". If the control plane advertises no `home_url`, say so instead of
29
+ inventing one, and say what `miakapp status` proved.
30
+ - **Ask once, at the start, and only for what you cannot find.** Access comes
31
+ from pairing (§9), the existing installation from inventory (§3). Repeated
32
+ permission questions in the middle of the work are a failure of the work.
33
+ - **You need nothing from the platform's source.** This guide and the published
34
+ CLI — including the app starter `miakapp init --starter app` writes — are the
35
+ whole toolchain for the interface. Never edit or redeploy the Miakapp
36
+ platform to make one house work; if a capability is missing, report it to the
37
+ owner as missing instead of patching around it.
38
+
39
+ Two scopes must not be confused:
40
+
41
+ | In scope by default | Needs the owner's explicit, separate request |
42
+ | --- | --- |
43
+ | reading the existing installation (§3) | changing flows, automations, brokers or devices that already run the house |
44
+ | writing and testing a coordinator and an app | granting a physical action (heat, lock, unlock, open, close) that the owner has not named |
45
+ | publishing, verifying and rolling back the V4 interface | anything on the owner's own machines beyond the coordinator you were asked to run |
46
+
47
+ Caution about the second column is not a reason to withhold the first. A new V4
48
+ interface that only reads is still a useful, publishable V1; say plainly which
49
+ controls are not offered and why.
50
+
13
51
  ## 1. What you are building
14
52
 
15
53
  Three artifacts, and no more:
@@ -17,18 +55,36 @@ Three artifacts, and no more:
17
55
  | Artifact | Where it runs | What it owns |
18
56
  | --- | --- | --- |
19
57
  | Coordinator | the owner's machine, under Bun | state, events, functions, **authorization** |
20
- | Component | a sandboxed Worker in the household's browser | the interface |
21
- | `miakapp.yaml` | neither; it is the contract | what the component may ask for |
58
+ | Interface | an isolated frame in the household's browser | what residents see and touch |
59
+ | `miakapp.yaml` | neither; it is the contract | what the interface may ask for |
60
+
61
+ The interface is a **whole-house application** (`app:` in `miakapp.yaml`, ABI
62
+ `miakapp.app/1`): your own HTML, CSS, layout, navigation and libraries, bundled
63
+ into one file. Miakapp draws nothing for you, and no longer draws the old
64
+ semantic `component:` kind at all: a home published that way shows as having no
65
+ interface. §5 covers the app.
22
66
 
23
- The coordinator is trusted. The component is not. The relay between them is
67
+ The coordinator is trusted. The interface is not. The relay between them is
24
68
  platform-untrusted but not blind: it terminates TLS, stores plaintext state and
25
69
  enforces routing, so self-hosting it does not give end-to-end confidentiality.
26
70
  Do not tell the owner otherwise.
27
71
 
28
- Start from `templates/home`. It is a complete working home — one lamp, one
29
- temperature — with the three files already in the right relationship, and its
30
- own `README.md` covering the mechanics of copying it out. This guide covers the
31
- judgment the template cannot.
72
+ Start the interface with the starter the CLI ships, in an empty directory:
73
+
74
+ ```bash
75
+ miakapp init --starter app # home and issuer from the paired context
76
+ bun run build && bun run check # Bun >= 1.2.23 bundles; Node >= 22.9 runs the CLI
77
+ ```
78
+
79
+ It writes `miakapp.yaml`, `app/main.ts` (the interface to edit),
80
+ `app/miakapp.ts` (the bridge to the home, copied from this CLI release),
81
+ `package.json`, `tsconfig.json` and `app/README.md`. It needs no source
82
+ repository and no unpublished package, and it refuses — writing nothing — if
83
+ any of those files already exists. As generated it shows only what the home
84
+ shares, with an honest empty state; it is where your work starts, never what
85
+ you publish. Without `--starter`, `init` writes `miakapp.yaml` alone.
86
+
87
+ This guide covers the judgment no starter can.
32
88
 
33
89
  ### Leave the repository readable by the next agent
34
90
 
@@ -53,7 +109,7 @@ that contradicts the CLI installed beside it is worse than no guide.
53
109
 
54
110
  **The coordinator authorizes everything.** The relay proves *who* is calling and
55
111
  attaches non-spoofable caller metadata. Deciding whether that person *may* act is
56
- the coordinator's job and nobody else's. In the template that decision is the
112
+ the coordinator's job and nobody else's. In a well-built coordinator that decision is the
57
113
  first line of the function body:
58
114
 
59
115
  ```ts
@@ -65,17 +121,17 @@ if (call.source.kind !== 'user' || call.source.id !== options.ownerUserId) {
65
121
  Removing that check does not produce an error anywhere. It produces a home that
66
122
  anyone enrolled can drive. There is no second layer that will catch it for you.
67
123
 
68
- **The component trusts nothing it was not given.** It has no network, no storage
69
- and no DOM. It cannot reach the lamp except through a call the coordinator
70
- declared, and it cannot read a state path the coordinator did not grant. This is
71
- why it is safe to let a component be rewritten often and reviewed lightly, and
72
- why it is not safe to move a decision into it.
124
+ **The app trusts nothing it was not given.** It has no network and no storage
125
+ shared with anyone. It cannot reach the lamp except through a call the
126
+ coordinator declared, and it cannot read a state path the coordinator did not
127
+ grant. This is why it is safe to let an app be rewritten often and reviewed
128
+ lightly, and why it is not safe to move a decision into it.
73
129
 
74
130
  **You own the UI; the coordinator owns the facts.** The coordinator exposes state
75
131
  and actions. What the household actually sees — the layout, the wording, the
76
- language, which controls are prominent — is yours to design from the semantic
77
- vocabulary in §5. Do not push presentation choices into the coordinator, and do
78
- not push authorization into the component.
132
+ language, which controls are prominent — is yours to design (§5). Do not push
133
+ presentation choices into the coordinator, and do not push authorization into
134
+ the app.
79
135
 
80
136
  ## 3. Before you write anything: characterize the house
81
137
 
@@ -94,6 +150,37 @@ Write down what you found before you write the configuration. The state paths yo
94
150
  choose become a disclosure boundary and a public interface at the same time, and
95
151
  renaming one after the household has used it is not free.
96
152
 
153
+ ### The inventory comes before the design
154
+
155
+ Commit the inventory as `docs/inventory.md` in the home repository, one line per
156
+ datum or action, before you design a single screen:
157
+
158
+ | Field | Example |
159
+ | --- | --- |
160
+ | source | `zigbee2mqtt/salon_thermo` over the house broker |
161
+ | what it is | temperature, °C, one decimal |
162
+ | how fresh | reports every ~60 s; last seen 2 min ago |
163
+ | who may read it | every member / owner only |
164
+ | command | none — a measurement, not a control |
165
+
166
+ Then design **from** it: the V1 shows every datum the household would care
167
+ about and every action that is both technically possible and authorized,
168
+ grouped the way people live in the house — by room or by use, not by device
169
+ or protocol. Anything you leave out, leave out on purpose, and say why in the
170
+ inventory. A V1 that shows three values when the house reports twenty is not a
171
+ first version; it is an unfinished one.
172
+
173
+ What the interface must never do:
174
+
175
+ - **invent data.** A value with no source is shown as absent, never filled in
176
+ with a plausible number or a demo fixture;
177
+ - **blur freshness.** Distinguish *current*, *stale* (with its age) and
178
+ *unavailable* for every value, in words a resident understands;
179
+ - **spend space on plumbing.** No protocol or platform vocabulary
180
+ (`ACCEPTED`, "relay connected", ABI, schema names, IDs), no banner restating
181
+ that a view is read-only, no title repeating the home's name on every card.
182
+ Every line of text is either information or an action.
183
+
97
184
  ### Reading a V3 house you inherited
98
185
 
99
186
  Most houses arriving at V4 already run Node-RED with the v3 MiakAPI nodes. Ask
@@ -135,7 +222,7 @@ keyword list should make it for you.
135
222
 
136
223
  ## 4. The coordinator
137
224
 
138
- `templates/home/coordinator/home.ts` is the shape to copy: the configuration is a
225
+ Keep the coordinator in the same shape: the configuration is a
139
226
  **pure function of its options**, so it can be tested without a relay, a control
140
227
  plane or a network. `coordinator/main.ts` is the only file that touches the
141
228
  outside world. Keep that split. It is what makes `test/home.test.ts` possible,
@@ -145,8 +232,8 @@ Four declarations:
145
232
 
146
233
  ```ts
147
234
  {
148
- state: { 'zone.salon.light.on': false }, // paths and initial values
149
- stateAccess: [{ userId, patterns: ['zone.salon.*'] }],
235
+ state: { 'zone.living_room.light.on': false }, // paths and initial values
236
+ stateAccess: [{ userId, patterns: ['zone.living_room.*'] }],
150
237
  events: [{ topic, directions: EventDirection.publishToUsers }],
151
238
  eventAccess: [{ userId, publish: [], subscribe: [topic] }],
152
239
  functions: { async 'lighting.set'(call) { /* authorize, act, return */ } },
@@ -171,7 +258,7 @@ see the old value. The reverse order is a race that will reproduce once a month
171
258
  and waste a day.
172
259
 
173
260
  **Reject bad arguments with a typed application error.** `ApplicationCallError`
174
- carries a numeric code the component can branch on. Do not throw a bare `Error`
261
+ carries a numeric code the app can branch on. Do not throw a bare `Error`
175
262
  for a caller mistake; the distinction between "you asked wrongly" and "something
176
263
  broke" is the one the interface needs most.
177
264
 
@@ -180,42 +267,51 @@ The relay keeps ownership tables for topics, state paths and functions, detects
180
267
  collisions and rejects with `4409`. If you claim `lighting.set` for the whole
181
268
  house, you have taken a name another integration may need; scope what you own.
182
269
 
183
- ## 5. The component
270
+ ## 5. The interface
184
271
 
185
- Import from `@miakapp/component`. The whole public surface is one module, and the
186
- whole rendering vocabulary is `ui.*`:
272
+ ### A whole-house application (default)
187
273
 
188
- ```
189
- screen stack grid section layout
190
- text status progress media output
191
- button toggle input select interaction
192
- ```
274
+ `miakapp init --starter app` writes an `app:` section and a buildable app to
275
+ edit. You own the document: build any DOM, ship your own CSS, route with
276
+ `location.hash`, use React, Svelte, Vue, charts or WebAssembly — anything a
277
+ bundler can inline. The deliverable is **one classic-script IIFE** of at most
278
+ 2 MiB, with no `import()` and no source map; the starter's `bun run build` is:
193
279
 
194
- You return one complete semantic tree per render; the trusted host draws it with
195
- its own components. You do not ship CSS, you do not ship a DOM, and you cannot
196
- style your way around the host. This is a constraint worth accepting rather than
197
- fighting: it is what lets the host stay accessible, themed and localized without
198
- auditing your code.
280
+ ```bash
281
+ bun build app/main.ts --format=iife --minify --outfile dist/app.js
282
+ ```
199
283
 
200
- Handlers are functions, not identifiers to wire up by hand:
284
+ Miakapp runs it in an isolated, opaque-origin frame below a permanent Miakapp
285
+ bar, after the resident agreed to open the home. The frame has no network, no
286
+ cookies or storage, no popups and no fullscreen; assets go in the bundle as
287
+ `data:`/`blob:` URLs. Its only way to the home is `window.miakapp`, through the
288
+ bridge the starter writes as `app/miakapp.ts` — the source of the `@miakapp/app`
289
+ SDK, which is not on npm yet, so import the local file:
201
290
 
202
291
  ```ts
203
- ui.toggle({
204
- id: 'salon-light',
205
- label: 'Lampe du salon',
206
- value: asBoolean(home.state.get(LIGHT_ON)),
207
- disabled: home.staging || !healthy,
208
- pending,
209
- onChange: (next) => void setLight(next),
210
- })
292
+ import { callErrorCode, connect } from './miakapp.js';
293
+
294
+ const home = connect();
295
+ home.subscribe((state) => render(state)); // also called once immediately
296
+ await home.call('lighting.set', { on: true }); // rejects with a closed code
211
297
  ```
212
298
 
213
- Handlers are registered for the render that created them, so a stale tree cannot
214
- fire an action against new state.
299
+ Do not edit the bridge; a newer CLI's starter carries any change to it.
300
+
301
+ **Make it beautiful from the first build.** Run `miakapp docs design` before you
302
+ draw anything: Miakapp ships design tokens, four themes (Minuit, Lumière, Miel,
303
+ Craie), CSS recipes, an embedded font and example screens. The starter's
304
+ `app/theme.ts` already uses them. They are a starting point you may change
305
+ entirely; the Miakapp bar outside your frame is not yours to redraw.
215
306
 
216
- The limits are real and enforced: 1 024 nodes, depth 32, 30 renders per second,
217
- 32 outstanding calls, 8 KiB per text node. If you are approaching any of them you
218
- are building a dashboard the household will not read.
307
+ Declare every state path (exact or `prefix.*`) under `app.requires.state_read`
308
+ and every function under `app.requires.call`. Events, media and `miakapp.*`
309
+ functions are refused by `miakapp check`. Show `state.stale`, disable controls
310
+ while it is true, and handle `outcome_unknown` exactly as below.
311
+
312
+ **The bundle is not private.** Any signed-in user who learns its digest can
313
+ fetch it. Put no household data in it — no names, rooms, devices or accounts —
314
+ and read everything from state, which the coordinator filters per resident.
219
315
 
220
316
  ### Two states the interface must never hide
221
317
 
@@ -224,7 +320,7 @@ house. Show it. Per RFC 0002 §12.2 it is exposed, never hidden — a thermostat
224
320
  reading that is silently forty minutes old is worse than one labelled uncertain.
225
321
 
226
322
  **Staging.** `home.staging` is true while a release is staged: rendering works,
227
- calls and events do not. Disable the controls and say why, as the template does.
323
+ calls and events do not. Disable the controls and say why.
228
324
  An interface that looks live and silently does nothing is the worst outcome
229
325
  available.
230
326
 
@@ -238,7 +334,7 @@ try {
238
334
  } catch (error) {
239
335
  // Deliberately not retried. The call may already have reached the lamp,
240
336
  // and the next state snapshot settles the question.
241
- failure = error instanceof Error ? error.message : 'La commande a échoué';
337
+ failure = error instanceof Error ? error.message : 'The command failed';
242
338
  }
243
339
  ```
244
340
 
@@ -250,7 +346,7 @@ code 7.
250
346
 
251
347
  ## 6. The intersection rule
252
348
 
253
- Every name a component may touch appears in **two** places, and the effective
349
+ Every name an app may touch appears in **two** places, and the effective
254
350
  grant is the intersection:
255
351
 
256
352
  | `miakapp.yaml` → `requires` | `coordinator/home.ts` |
@@ -261,14 +357,13 @@ grant is the intersection:
261
357
  | `call` | `functions` |
262
358
 
263
359
  Asking for more than the coordinator grants **does not fail loudly at
264
- publication**. The component simply never receives that path, and the interface
360
+ publication**. The app simply never receives that path, and the interface
265
361
  renders a hole — an empty card, a control that does nothing, a temperature that
266
362
  is permanently unavailable. This is the single most common way a Miakapp home
267
363
  breaks, and it breaks quietly.
268
364
 
269
- So: assert the correspondence in a test. `templates/home/test/home.test.ts` does
270
- exactly this, and it is the reason a mismatch fails in CI rather than in
271
- someone's living room. When you add a path, change four things in one commit —
365
+ So: assert the correspondence in a test, so a mismatch fails in CI rather than
366
+ in someone's living room. When you add a path, change four things in one commit —
272
367
  the state declaration, the access pattern, the `requires` entry, and the test.
273
368
 
274
369
  ## 7. The loop
@@ -281,8 +376,8 @@ Run it before every publication and in CI. It costs nothing and catches the
281
376
  artifact rules the runtime would reject anyway.
282
377
 
283
378
  Do not treat a check that exists as a check that runs. On 2026-09-14 this
284
- repository had a template and a component example that were both verified
285
- locally and built by nobody, because the workflow called `bun run check` and not
379
+ repository had two example packages that were both verified locally and built
380
+ by nobody, because the workflow called `bun run check` and not
286
381
  `check:packages`; when CI finally exercised them they failed three times in a
287
382
  row on defects that had been sitting there invisibly. If you add a package, add
288
383
  it to the job that runs in CI, then watch one run go green before believing it.
@@ -305,25 +400,35 @@ writes no history, rewrites no source it did not generate, and invents no
305
400
  control-plane endpoint. The repository is the owner's.
306
401
 
307
402
  ```bash
308
- miakapp agent-pack # once, per repository
309
- miakapp init --home <homeId> --control-plane <https url>
403
+ miakapp docs start # this guide, from the installed CLI
404
+ miakapp pair # once per home and machine (§9)
405
+ miakapp agent-pack # once, per repository
406
+ miakapp init --starter app # manifest + buildable app; plain init writes the manifest only
310
407
  miakapp check
311
- miakapp publish --expected-generation <n>
312
- miakapp activate --sha256 <digest> --expected-generation <n>
313
- miakapp rollback --sha256 <digest> --expected-generation <n> # alias of activate
408
+ miakapp status # what is live now: generation, release, digest
409
+ miakapp publish # upload, finalize, activate
410
+ miakapp status # verify the new digest is what is live
411
+ miakapp activate --sha256 <digest> # promote an already finalized digest
412
+ miakapp rollback --sha256 <digest> # alias of activate
314
413
  miakapp release <sha256> # read one finalized release
315
414
  miakapp upload <uploadId> # reconcile a lost request
316
415
  ```
317
416
 
318
- `--expected-generation` is a compare-and-swap on the home's component pointer: the
319
- generation you believe it currently holds. It is `0` for a home that has never
320
- published. It is required, and it is what stops two agents from silently
321
- overwriting each other.
417
+ Activation is a compare-and-set on the home's component pointer. Without
418
+ `--expected-generation` the CLI reads the live generation first and activates
419
+ the next one; the read takes no lock, so another publication landing in between
420
+ still fails with `conflict` instead of being overwritten. Pass
421
+ `--expected-generation <n>` when you want to assert the state you reviewed.
322
422
 
323
423
  Rollback is `activate` pointed at a digest you already trust. Keep the digest of
324
424
  every release you shipped; a rollback you can perform in one command is worth
325
425
  more than an incident you can explain.
326
426
 
427
+ `miakapp status` after `publish` is the minimum verification: the live `sha256`
428
+ must be the one you just built. It proves what the home runs, not that the
429
+ interface is right — open its `home_url` as a member would before telling the
430
+ owner it works.
431
+
327
432
  ### Driving the CLI as a program
328
433
 
329
434
  Every failure maps to exactly one stable exit code and one stable
@@ -366,22 +471,68 @@ Three differences are worth knowing before you call anything:
366
471
  `packages/cli/README.md` lists the tools. The exit codes above are the
367
472
  `exit_code` field in every result, so branch on the same table either way.
368
473
 
369
- ## 9. Secrets
474
+ ## 9. Access: pairing and contexts
475
+
476
+ You never sign in as the owner and never ask for a password, a Google login or
477
+ an existing key. The owner grants access to one home, in their own browser:
478
+
479
+ 1. Ask the owner to open **https://miakapp.com/pair**, sign in to their own
480
+ account, choose the home (or create it), confirm the access it grants, and
481
+ send you the one-time code it shows. A code works once, for ten minutes.
482
+ 2. Redeem it. The code is read from stdin and never echoed:
370
483
 
371
- `MIAKAPP_HOME_KEY` comes from the environment. It is never a command-line
372
- argument, never printed, never written into a project file. No command accepts
373
- one, deliberately: an argument lands in shell history, in a process listing and
374
- in most CI logs.
484
+ ```bash
485
+ printf '%s\n' "<code>" | miakapp pair # add --issuer <url> if the page shows one
486
+ ```
487
+
488
+ Over MCP, call `miakapp_pair` with `code`. Never repeat the code back in a
489
+ message, and never retry a refused code — ask for a new one.
490
+ 3. `pair` stores a **new, separately revocable** Home Key for this machine as a
491
+ context in `~/.miakapp`, keeps every other context, makes the new one
492
+ current, and proves the key can publish. It prints the key ID and label,
493
+ never the key.
375
494
 
376
495
  ```bash
377
- export MIAKAPP_HOME_KEY="$(your-secret-manager read miakapp/home-key)"
496
+ miakapp context list # every home this machine can publish to
497
+ miakapp context show [name] # one context; the key is never printed
498
+ miakapp context use <name> # make a context current
499
+ miakapp context remove <name> # delete it locally (the owner revokes it server-side)
378
500
  ```
379
501
 
380
- If you are about to write a secret into `miakapp.yaml` so something works, stop:
381
- that is the failure this design exists to prevent.
502
+ `~/.miakapp/config.json` holds names, homes, issuers and key IDs;
503
+ `credentials.json` holds the keys. Both are mode 0600 in a 0700 directory and
504
+ are replaced atomically; the CLI refuses a credentials file other accounts can
505
+ read. `MIAKAPP_CONFIG_DIR` relocates the directory.
506
+
507
+ Which key a command uses, highest precedence first:
508
+
509
+ 1. `--context <name>`, then `MIAKAPP_CONTEXT=<name>`;
510
+ 2. `MIAKAPP_HOME_KEY`, a raw key for CI and compatibility;
511
+ 3. the stored context paired with the home and issuer in `miakapp.yaml` — the
512
+ current context breaks a tie between two keys for that same home.
513
+
514
+ A context, or a known key, for a different home than `miakapp.yaml` names is
515
+ refused before any request: a key can never publish into the wrong house.
516
+
517
+ Prefer one key per agent or machine, so the owner can revoke one without
518
+ breaking the others. A coordinator running on the owner's machine still reads
519
+ its own key from its environment.
520
+
521
+ If you are about to write a secret into `miakapp.yaml` or any file in the
522
+ repository so something works, stop: that is the failure this design exists to
523
+ prevent.
382
524
 
383
525
  ## 10. Before you tell the owner you are done
384
526
 
527
+ - [ ] `docs/inventory.md` lists every source, datum and action you found, and
528
+ the interface covers it or says why not.
529
+ - [ ] Every value shows whether it is current, stale or unavailable; nothing is
530
+ invented, and no technical vocabulary is on screen.
531
+ - [ ] The interface is published, `miakapp status` shows your digest live, and
532
+ you opened it as a member would — or you say precisely what you could not
533
+ check.
534
+ - [ ] The owner received a working link and the rollback digest, not a
535
+ screenshot or a mockup.
385
536
  - [ ] Every physically consequential function authorizes its caller on its first
386
537
  line, and a test proves an unauthorized caller is refused.
387
538
  - [ ] Every name in `miakapp.yaml` is covered by the coordinator, and a test
@@ -390,19 +541,21 @@ that is the failure this design exists to prevent.
390
541
  - [ ] No call path retries an unknown outcome.
391
542
  - [ ] State is written before its event is published.
392
543
  - [ ] `bun run check` is green, and CI ran it — not just you.
393
- - [ ] The Home Key exists only in the environment.
544
+ - [ ] The Home Key exists only in `~/.miakapp` or the environment, never in the
545
+ repository.
394
546
  - [ ] You recorded the digest of what you published, so rollback is one command.
395
547
 
396
548
  ## Where to read further
397
549
 
550
+ Everything a home needs is above and in the CLI with its starter. The RFCs and
551
+ platform paths below explain *why* the platform behaves as it does; you never
552
+ need them, or the platform repository, to build and publish a home.
553
+
398
554
  - `packages/cli/README.md` — every command and every tool, including what the
399
555
  pack writes and what it refuses to overwrite.
400
- - `templates/home/README.md` — the mechanics of the template itself.
401
556
  - `docs/rfcs/0001` (Miakapp-V3) — wire protocol: ownership, collisions, `4409`.
402
- - `docs/rfcs/0002` — component runtime and the staleness rule. **The broker is
403
- the authority for the guest ABI, not the RFC**: `component-runtime/src/runtime-broker.ts`
404
- and `contract.ts` define the exact payloads, and the broker terminates the
405
- instance rather than answering when a field is wrong.
557
+ - `docs/rfcs/0002` — release pointer, capabilities and the staleness rule;
558
+ `docs/specs/2026-10-03-house-app-abi.md` — the app frame and its bridge.
406
559
  - `docs/rfcs/0003` — the coordinator SDK surface.
407
560
  - `docs/rfcs/0004` — Home Key bootstrap, scopes, publication.
408
561
  - `docs/rfcs/0005` — the trusted browser client.
@@ -0,0 +1,93 @@
1
+ Copyright 2019 The Manrope Project Authors (https://github.com/sharanda/manrope)
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.