create-githolon 0.69.3 → 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.
|
|
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`.
|