@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.
- package/README.md +151 -35
- package/assets/agent-guide.md +232 -79
- package/assets/design/OFL-Manrope.txt +93 -0
- package/assets/design/components.css +139 -0
- package/assets/design/fonts.css +9 -0
- package/assets/design/gallery.html +667 -0
- package/assets/design/guide.md +77 -0
- package/assets/design/tokens.css +185 -0
- package/assets/starter/app/app/README.md +74 -0
- package/assets/starter/app/app/main.ts +124 -0
- package/assets/starter/app/app/miakapp.ts +156 -0
- package/assets/starter/app/app/theme.ts +8 -0
- package/assets/starter/app/tsconfig.json +23 -0
- package/bin/miakapp.js +5 -1
- package/dist/agent-pack.d.ts +11 -3
- package/dist/agent-pack.d.ts.map +1 -1
- package/dist/agent-pack.js +26 -10
- package/dist/agent-pack.js.map +1 -1
- package/dist/contexts.d.ts +59 -0
- package/dist/contexts.d.ts.map +1 -0
- package/dist/contexts.js +388 -0
- package/dist/contexts.js.map +1 -0
- package/dist/control-plane.d.ts +14 -0
- package/dist/control-plane.d.ts.map +1 -1
- package/dist/control-plane.js +33 -1
- package/dist/control-plane.js.map +1 -1
- package/dist/internal/names.d.ts +5 -0
- package/dist/internal/names.d.ts.map +1 -1
- package/dist/internal/names.js +6 -0
- package/dist/internal/names.js.map +1 -1
- package/dist/main.d.ts +22 -5
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +673 -60
- package/dist/main.js.map +1 -1
- package/dist/mcp.d.ts +7 -1
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +195 -26
- package/dist/mcp.js.map +1 -1
- package/dist/pairing.d.ts +27 -0
- package/dist/pairing.d.ts.map +1 -0
- package/dist/pairing.js +148 -0
- package/dist/pairing.js.map +1 -0
- package/dist/project.d.ts +3 -1
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +33 -6
- package/dist/project.js.map +1 -1
- package/dist/publication.d.ts +20 -5
- package/dist/publication.d.ts.map +1 -1
- package/dist/publication.js +58 -16
- package/dist/publication.js.map +1 -1
- package/dist/starter.d.ts +17 -0
- package/dist/starter.d.ts.map +1 -0
- package/dist/starter.js +72 -0
- package/dist/starter.js.map +1 -0
- package/dist/terminal.d.ts +10 -0
- package/dist/terminal.d.ts.map +1 -0
- package/dist/terminal.js +70 -0
- package/dist/terminal.js.map +1 -0
- package/dist/version.d.ts +15 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +15 -0
- package/dist/version.js.map +1 -0
- package/package.json +6 -4
package/assets/agent-guide.md
CHANGED
|
@@ -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
|
-
|
|
|
21
|
-
| `miakapp.yaml` | neither; it is the contract | what the
|
|
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
|
|
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
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
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
|
|
69
|
-
|
|
70
|
-
declared, and it cannot read a state path the coordinator did not
|
|
71
|
-
why it is safe to let
|
|
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
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
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.
|
|
149
|
-
stateAccess: [{ userId, patterns: ['zone.
|
|
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
|
|
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
|
|
270
|
+
## 5. The interface
|
|
184
271
|
|
|
185
|
-
|
|
186
|
-
whole rendering vocabulary is `ui.*`:
|
|
272
|
+
### A whole-house application (default)
|
|
187
273
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
|
|
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
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
-
|
|
214
|
-
|
|
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
|
-
|
|
217
|
-
|
|
218
|
-
are
|
|
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
|
|
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 : '
|
|
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
|
|
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
|
|
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
|
|
270
|
-
|
|
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
|
|
285
|
-
|
|
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
|
|
309
|
-
miakapp
|
|
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
|
|
312
|
-
miakapp
|
|
313
|
-
miakapp
|
|
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
|
-
|
|
319
|
-
generation
|
|
320
|
-
|
|
321
|
-
|
|
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.
|
|
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
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
-
|
|
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
|
-
|
|
381
|
-
|
|
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` —
|
|
403
|
-
|
|
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.
|