create-githolon 0.69.2 → 0.70.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-githolon",
3
- "version": "0.69.2",
3
+ "version": "0.70.0",
4
4
  "type": "module",
5
5
  "description": "Scaffold a Nomos domain package: the starter domain + compile config + live e2e. `npm create githolon my-app`.",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -264,6 +264,54 @@ Cloud's own usage tenant folds a reading AND its budget meter in ONE intent —
264
264
  so the budget invariant judges both together: a reading that would leave the
265
265
  meter over an unacked threshold refuses, and the sample refuses WITH it.
266
266
 
267
+ ## Roles — sugar over relations (the kernel is the authority)
268
+
269
+ A `role(...)` is the highest-level authz surface: it LOWERS onto the ONE ReBAC
270
+ spine (relation tuples + the kernel gate). It is pure sugar — there is NO
271
+ role-array membership check anywhere; every capability is a relation tuple the
272
+ kernel judges.
273
+
274
+ ```ts
275
+ import { role, aggregate, t, Lww, requires, directive, create } from "@githolon/dsl";
276
+
277
+ export const editor = role("editor"); // .edit / .view refs available immediately
278
+
279
+ export const Note = aggregate("Note",
280
+ { author: t.string().merge(Lww), body: t.string().merge(Lww) },
281
+ { visibility: requires(editor.view) }); // Note is private behind the role's VIEW cap
282
+
283
+ // EMIT the role's grant/revoke/seed directives + relation schema (auto-discovered by shape):
284
+ export const noteRoles = editor.canEdit(Note).canView(Note).grantableBy("admin").emit();
285
+
286
+ // Wire the role's EDIT ref onto a mutating directive — only an editor may write:
287
+ export const editNote = directive("editNote")
288
+ .creates(Note)
289
+ .payload(z.object({ author: z.string().min(1), body: z.string().min(1) }))
290
+ .plan((p) => { create(Note).set("author", p.author).set("body", p.body); return []; })
291
+ .requires(editor.edit);
292
+ ```
293
+
294
+ What `editor…emit()` gives you:
295
+
296
+ - **Relation schema with TEETH** — the `editorEdit` write relation is authored
297
+ into the law, so `.requires(editor.edit)` never fails open (the fail-open
298
+ footgun is closed); `editorView` is a read-visibility cap (wire it as an
299
+ aggregate `requires(editor.view)`).
300
+ - **Grant / revoke / seed directives** — `grantEditor` / `revokeEditor` seat or
301
+ remove the role's relation tuple, gated `.requires("admin")` (the kernel judges
302
+ the granter). `seedEditor` seats the `admin` grant-authority on a founding
303
+ principal at genesis/birth (ungated seed lane).
304
+ - **Typed policy refs** — `editor.edit` / `editor.view` (never strings) for
305
+ `.requires(...)` and aggregate visibility.
306
+ - **`canEdit<Agg>` / `canView<Agg>` codegen** (TS + Dart) — UI-hint helpers that
307
+ mirror the kernel's check over the folded tuples. **INFORMATIONAL only — the one
308
+ wasm gate is the authority and refuses regardless of what the helper returns.**
309
+ Use them to grey out a button, never to decide access.
310
+
311
+ Roles are workspace-scoped (the read-visibility gate is workspace-scoped in the
312
+ kernel). Per-record grants stay available via the lower-level
313
+ `.requires(rel, { objectFrom })` axis. `grantableBy` defaults to `admin`.
314
+
267
315
  ## Determinism or death
268
316
 
269
317
  A plan is a PURE function of its payload. No `Date.now()`, no
@@ -92,3 +92,12 @@ npx githolon proof # OFFLINE: drives your .births() directive on the real
92
92
  A red proof names the exact genesis step the child's gate refused. The most common first-timer halt: a
93
93
  plan that returns a fluent builder — builders record themselves, so end the plan with `return [];`.
94
94
  A complete working two-domain births package to copy: `bench/scale/fixtures/estate-birth` (nomos2 repo).
95
+
96
+ ## Posture at birth
97
+
98
+ `birthChild` / `createWorkspace` take an optional `posture: "managed" | "sovereign"` (default **managed**)
99
+ — the child's declared governance posture, mirrored onto its lineage record. A **Managed** child can be
100
+ recovered by the operator on request (a rebirth heal = "ask us"); a **Sovereign** child's rebirth requires
101
+ the child's own consent fact first (a heal = consent first). See
102
+ [11-governance-postures.md](./11-governance-postures.md) for the two postures, the consent ceremony, and
103
+ the exit rights.
@@ -0,0 +1,89 @@
1
+ # Governance postures — Managed and Sovereign
2
+
3
+ Every platform you run on Nomos Cloud **declares a governance posture**. It decides one thing: **may the
4
+ operator (the root custodian) run recovery verbs — rebirth, certifyEra, repairs — FOR your workspace
5
+ without asking you first?** Both postures are first-class; you choose, and you can change your mind.
6
+
7
+ The honest foundation, stated plainly and never hidden:
8
+
9
+ - **Validity sovereignty is absolute for everyone.** Holons self-verify. The operator can *act* but can
10
+ never *lie* — every operator act is a signed, ordered, permanent fact in root's replayable chain.
11
+ - **Custody power is irreducibly the host's while you are hosted.** No cryptography stops a landlord
12
+ changing the locks. What Nomos gives you is **detectability** (a custody break fails closed) and
13
+ **exit** (clone the ledger and leave — the byte-identical wasm makes self-hosting the ultimate exit).
14
+ - Therefore **hosted sovereignty = law-encoded restraint + total detectability + credible exit.** Never
15
+ prevention.
16
+
17
+ ## Posture A — Managed (the default)
18
+
19
+ Your platform's law folds an **OperatorGrant**: the root custodian may run recovery verbs for you — each
20
+ a signed, attributed law fact + certificate you audit forever. This is *the assurance of being able to
21
+ ask us for help*: if your chain scars unrecoverably, we can rebirth it for you without a ceremony.
22
+
23
+ A workspace with **no posture fact at all is Managed** — that is the default, and nothing changes for a
24
+ platform that never touches postures.
25
+
26
+ ## Posture B — Sovereign
27
+
28
+ No OperatorGrant. Your founding key is terminal for your subtree's law. **The teeth:** root's
29
+ `rebirthWorkspace` REFUSES for a Sovereign workspace unless the offer carries **your consent** — a
30
+ `RebirthConsent` fact folded in **your own chain**, signed by your own admin, in your own history. The
31
+ two-key ceremony: the custody act cannot move without BOTH root's law fact AND your consent fact.
32
+ Operator restraint becomes law that replays, not policy you have to trust.
33
+
34
+ ### The honest ceiling (read this)
35
+
36
+ > The operator controls root's law and could deploy law removing the consent check — but that act is
37
+ > itself a signed, ordered, permanent fact in root's chain, visible to every tenant running `replay root`,
38
+ > and grounds for exit-with-everything. Not "we can't" — "we can't secretly, and you can always leave."
39
+
40
+ ## Declaring and changing your posture
41
+
42
+ Posture is **law-state in your own chain** (you own the fact), mirrored onto root's lineage record so the
43
+ bailiff can consult it on the hot path without reading every tenant chain. **The tenant chain is
44
+ authoritative — a mirror mismatch fails closed to Sovereign.**
45
+
46
+ ```bash
47
+ # see the current posture, the consent state, and exactly what it means
48
+ githolon posture <platform>
49
+
50
+ # withdraw the operator grant (Managed → Sovereign) — forward-only; help already given stays in history
51
+ githolon posture set <platform> sovereign --reason "we run our own recovery from here"
52
+
53
+ # re-invite help (Sovereign → Managed)
54
+ githolon posture set <platform> managed --reason "hand recovery back to the operator"
55
+ ```
56
+
57
+ You can also declare a posture **at birth**: `birthChild` / `createWorkspace` take an optional
58
+ `posture: "managed" | "sovereign"` (default managed), mirrored onto the child's lineage record.
59
+
60
+ ## The consent ceremony (Sovereign rebirth)
61
+
62
+ When a Sovereign workspace needs a rebirth, the operator plans it but **cannot proceed until you consent
63
+ in your own chain**:
64
+
65
+ ```bash
66
+ # operator: sees the block up front
67
+ githolon rebirth plan <ws> # GOVERNANCE POSTURE → SOVEREIGN, consent ABSENT → refused pre-seed
68
+
69
+ # tenant: fold the consent fact in YOUR OWN chain (signed by your admin)
70
+ githolon consent rebirth <ws> --reason "authorising the reborn incarnation" [--expires-at <epoch-ms>]
71
+
72
+ # operator: now the two-key ceremony is satisfied — the rebirth admits
73
+ githolon rebirth apply --plan rebirths/<date>-<ws>/plan.json --gcp-secret nomos-root-custodian-key
74
+ ```
75
+
76
+ Without a live consent fact, both the CLI (`rebirth apply`) and the custody act itself (a `428` refusal)
77
+ decline and name the exact `githolon consent rebirth` command you need. Consent is forward-only and may
78
+ carry an `expiresAt` window.
79
+
80
+ ## Recursion and exit
81
+
82
+ A platform is root-for-its-subtree: it offers **its** children the same postures with its founding key in
83
+ the operator role. **Custody does not nest** — a Sovereign sub-platform still rides the grandparent's
84
+ bailiff; true custody independence is self-hosting (clone the ledger, run the byte-identical wasm
85
+ yourself). No level ever rebirths itself; root operations stay the one extra-legal act, always named in
86
+ CLI output.
87
+
88
+ See also: [08-births.md](./08-births.md) (a Managed heal = "ask us"; a Sovereign heal = consent first) and
89
+ the ratified spec `architecture/governance_postures.md`.