@githolon/dsl 0.1.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.
Files changed (53) hide show
  1. package/LICENSE.md +36 -0
  2. package/compile_package.mjs +50 -0
  3. package/package.json +59 -0
  4. package/src/aggregate.ts +167 -0
  5. package/src/authoring.ts +119 -0
  6. package/src/build_package.ts +636 -0
  7. package/src/certified_read.ts +313 -0
  8. package/src/codegen_dart.ts +2732 -0
  9. package/src/codegen_dot.ts +466 -0
  10. package/src/codegen_provider_dart.ts +358 -0
  11. package/src/codegen_ts.ts +365 -0
  12. package/src/codegen_usda.ts +388 -0
  13. package/src/combined.ts +195 -0
  14. package/src/compile_engine.ts +567 -0
  15. package/src/compile_package_main.ts +496 -0
  16. package/src/compose.ts +317 -0
  17. package/src/count.ts +218 -0
  18. package/src/ctx.ts +57 -0
  19. package/src/derived.ts +138 -0
  20. package/src/directive.ts +306 -0
  21. package/src/drivers.ts +95 -0
  22. package/src/emits_guard.ts +123 -0
  23. package/src/engine_entry.ts +449 -0
  24. package/src/exists.ts +170 -0
  25. package/src/extremum.ts +227 -0
  26. package/src/fields.ts +291 -0
  27. package/src/framework/bootstrap.ts +22 -0
  28. package/src/framework/disclosure.ts +108 -0
  29. package/src/framework/domain_lifecycle.ts +108 -0
  30. package/src/framework/identity.ts +537 -0
  31. package/src/framework/impure_capability.ts +643 -0
  32. package/src/framework/rbac.ts +418 -0
  33. package/src/framework/repair.ts +150 -0
  34. package/src/framework/sync_lifecycle.ts +125 -0
  35. package/src/framework/workspace_invariant.ts +128 -0
  36. package/src/framework/workspaces.ts +817 -0
  37. package/src/index.ts +317 -0
  38. package/src/manifest.ts +947 -0
  39. package/src/ops.ts +145 -0
  40. package/src/ordered_read.ts +228 -0
  41. package/src/predicate.ts +203 -0
  42. package/src/query/compile.ts +0 -0
  43. package/src/query/relations.ts +144 -0
  44. package/src/query.ts +151 -0
  45. package/src/read.ts +54 -0
  46. package/src/relation.ts +189 -0
  47. package/src/report/csv.ts +54 -0
  48. package/src/report.ts +401 -0
  49. package/src/spatial.ts +115 -0
  50. package/src/sum.ts +194 -0
  51. package/src/usd.ts +563 -0
  52. package/src/wire.ts +149 -0
  53. package/src/wire_encode.ts +250 -0
@@ -0,0 +1,817 @@
1
+ // NOMOS — Nomos Sovereign: participants act · verify · remember LOCALLY; hosted
2
+ // remotes are replaceable custody/transport, not truth. ⇒ ONE Nomos GitHolon
3
+ // wasm32-wasip1 artifact {kernel · projection · embedded
4
+ // QuickJS engine} on V8 + WASI-shim, byte-identical everywhere. V8 = portability; the one
5
+ // wasm = determinism. No native, no wasmtime, no 2nd artifact, no domain-JS on bare V8.
6
+ // If a file isn't this / hosting this / authoring for this / proving this — it's gone.
7
+
8
+ /**
9
+ * THE GOVERNANCE DOMAIN — the law under which ALL access to Nomos Cloud is governed.
10
+ *
11
+ * The constitution (Jack): "one's whole access to the nomos cloud is governed by
12
+ * nomos. Our access as admins should be governed by nomos." There is NO out-of-band
13
+ * power: every workspace that exists, every admin key that may act, every key that
14
+ * may create a workspace, is a LAW-STATE FACT in the root governance workspace —
15
+ * authored through these directives, admitted under this domain's own law, ledgered
16
+ * in git like any other intent. The split of powers:
17
+ *
18
+ * * the LAW DECIDES — this domain's aggregates are the only registry of authority.
19
+ * "Is this bearer an admin?" is `adminGrantByKeyHash(sha256(bearer))` with
20
+ * `status == "active"`. Nothing else answers that question.
21
+ * * the WORKER ENFORCES — the cloud worker is a dumb bailiff: it hashes the
22
+ * presented bearer (sha256 hex, never stored, never logged), probes the law
23
+ * state through the declared queries below, and obeys the verdict. It holds no
24
+ * key list of its own and can grant nothing.
25
+ *
26
+ * THE WORLD RESTS ON A BIRTH UID. Every holon on the platform has a PARENT, and the
27
+ * tree bottoms out in ONE auth-provider principal uid — the genesis principal. Root
28
+ * authors its own birth ({@link birthCloud}) into its own chain under this very law:
29
+ * `parent: ""`, `principal: <the genesis uid>`. Every workspace born after that is
30
+ * parented to root's `CloudWorkspace` record and carries the principal its request
31
+ * CLAIMED. For now claims are taken at their word — the only authority granted is
32
+ * the authority of the request, propagated via nomos intents; a real auth layer
33
+ * later verifies the same claims without changing one line of this law. (Custody
34
+ * facts, never validity: lineage records who birthed a holon, not whether its chain
35
+ * is true — replay decides truth.)
36
+ *
37
+ * GENESIS: stage zero seeds the founding `AdminGrant` (the hash of the first admin
38
+ * secret) via one `grantAdmin` dispatch — and then the bootstrap env var DIES. From
39
+ * that moment authority changes hands only through `grantAdmin` / `revokeAdmin` /
40
+ * `grantCreation` / `revokeCreation`, each itself an admitted, attributed,
41
+ * replayable intent. Losing the ledger loses nothing (git custody); losing the env
42
+ * var loses nothing (it was spent at genesis).
43
+ *
44
+ * SECRETS NEVER ENTER THE LEDGER. Only sha256-hex digests (`keyHash` /
45
+ * `ownerGrantHash`) are law state. The worker mints workspace owner secrets,
46
+ * returns them ONCE to the caller, and authors only the hash here.
47
+ *
48
+ * THE WORKSPACE LIFECYCLE is two-phase by design (law first, machinery second):
49
+ * 1. `createWorkspace` records the REQUEST — a minted `CloudWorkspace` with
50
+ * status "requested" and an EMPTY `ownerGrantHash` (no bearer exists yet).
51
+ * 2. The worker PHYSICALLY provisions (Artifacts repo + holon boot), mints the
52
+ * owner secret, and authors `provisionWorkspace` with its hash — status
53
+ * "provisioned". A workspace the law never heard of cannot be provisioned;
54
+ * a provision the law refused never happened.
55
+ *
56
+ * DETERMINISM RULES (engine-enforced; design for them):
57
+ * * every timestamp is EPOCH-MS `t.int()`, stamped by the CALLER and carried in
58
+ * the payload — a plan never calls `Date.now()`;
59
+ * * `.creates` directives accept NO id — Nomos MINTS every aggregate id;
60
+ * * all scalars are `Lww` (kernel-lowered), so this domain is fully present in
61
+ * the identity manifest — admission never fail-closes on a palette gap.
62
+ */
63
+ import { z } from "zod";
64
+ import { aggregate, instance } from "../aggregate.js";
65
+ import { create } from "../authoring.js";
66
+ import { directive } from "../directive.js";
67
+ import { Lww } from "../drivers.js";
68
+ import { t } from "../fields.js";
69
+ import { set, withMarker } from "../ops.js";
70
+ import { query } from "../query.js";
71
+
72
+ // --- vocabulary ----------------------------------------------------------------
73
+
74
+ /** Where a workspace's holon runs: an edge DO or the dedicated 12GiB container. */
75
+ export const WORKSPACE_TIERS = ["edge", "heavy"] as const;
76
+
77
+ /**
78
+ * The workspace lifecycle: `requested` (law fact only — nothing physical exists)
79
+ * → `provisioned` (the worker built the machinery and recorded the owner hash)
80
+ * → `retired` (the law has withdrawn it; the worker refuses its bearers).
81
+ */
82
+ export const WORKSPACE_STATUSES = ["requested", "provisioned", "retired"] as const;
83
+
84
+ /** A grant is `active` until the law revokes it — revocation is permanent. */
85
+ export const GRANT_STATUSES = ["active", "revoked"] as const;
86
+
87
+ /** sha256 hex — the ONLY shape a credential may take inside the law. */
88
+ const sha256Hex = z.string().regex(/^[0-9a-f]{64}$/, "expected lowercase sha256 hex");
89
+
90
+ /** Epoch-ms, caller-stamped (a plan never reads a clock). */
91
+ const epochMs = z.number().int().nonnegative();
92
+
93
+ // --- aggregates ------------------------------------------------------------------
94
+
95
+ /**
96
+ * CloudWorkspace — the law-state record of one hosted workspace (one edge/heavy
97
+ * holon + its Artifacts repo). Its EXISTENCE here is what makes the physical
98
+ * workspace legitimate; the worker provisions nothing the law has not requested
99
+ * and serves nothing the law has retired.
100
+ *
101
+ * `ownerGrantHash` is the workspace-owner credential ON FILE: the sha256 hex of
102
+ * the owner secret the worker minted at provision time. The worker checks a
103
+ * presented owner bearer against THIS field — the law record, not a worker-side
104
+ * secret store. `""` until provisioned.
105
+ */
106
+ export const CloudWorkspace = aggregate("CloudWorkspace", {
107
+ /** Human-meaningful unique workspace name (the `:ws` URL segment). */
108
+ name: t.string().merge(Lww),
109
+ /** Parent CloudWorkspace AGGREGATE id, or `""` for a root workspace. */
110
+ parent: t.string().merge(Lww),
111
+ /**
112
+ * The auth-provider principal uid the birth request CLAIMED — taken at its word
113
+ * for now (the auth layer that verifies claims comes later; the law's shape does
114
+ * not change when it does). `""` on legacy records born before the lineage story.
115
+ */
116
+ principal: t.string().merge(Lww),
117
+ /** Hosting tier — `edge` (DO) or `heavy` (12GiB container). */
118
+ tier: t.enum(WORKSPACE_TIERS).merge(Lww),
119
+ /** Lifecycle: requested → provisioned → retired. */
120
+ status: t.enum(WORKSPACE_STATUSES).merge(Lww),
121
+ /** sha256 hex of the workspace owner secret; `""` until provisioned. */
122
+ ownerGrantHash: t.string().merge(Lww),
123
+ /** Who asked for it (an admin/creation-grant principal label). */
124
+ createdBy: t.string().merge(Lww),
125
+ /** Epoch-ms the request was authored (caller-stamped). */
126
+ createdAt: t.int().merge(Lww),
127
+ /** Epoch-ms the worker completed physical provisioning; absent until then. */
128
+ provisionedAt: t.int().merge(Lww).optional(),
129
+ /**
130
+ * Per-workspace cumulative-ledger byte cap OVERRIDE (bytes); absent = the
131
+ * cloud-wide {@link CloudPolicy} default applies. Raised on the record via
132
+ * {@link setWorkspaceByteCap} — a granted quota request.
133
+ */
134
+ byteCap: t.int().merge(Lww).optional(),
135
+ /**
136
+ * What this node IS: absent/`"workspace"` = a leaf; `"platform"` = a PLATFORM —
137
+ * a workspace that hosts the SAME governance law and parents its own subtree
138
+ * (the cloud, one level down; born via {@link birthPlatform}).
139
+ */
140
+ kind: t.enum(["workspace", "platform"]).merge(Lww).optional(),
141
+ /**
142
+ * PLATFORM ONLY — the POOL: how many live child workspaces this platform may
143
+ * parent. Children draw from the platform's pool, never from their end-users'
144
+ * personal allowances; how the platform slices its pool among its own users is
145
+ * its OWN law's business. Raised via {@link setPlatformPool} (a granted quota
146
+ * request at the cloud level).
147
+ */
148
+ pool: t.int().merge(Lww).optional(),
149
+ });
150
+
151
+ /**
152
+ * AdminGrant — one admin credential of the cloud itself. An `active` AdminGrant's
153
+ * `keyHash` is the WHOLE of admin power: the worker admits an admin bearer iff
154
+ * `adminGrantByKeyHash(sha256(bearer))` yields an active grant. Genesis seeds the
155
+ * first one; after that, admins make admins — on the record.
156
+ */
157
+ export const AdminGrant = aggregate("AdminGrant", {
158
+ /** sha256 hex of the admin bearer secret (the secret itself never lands here). */
159
+ keyHash: t.string().merge(Lww),
160
+ /** Human label for audit ("jack", "ci-deployer", ...). */
161
+ label: t.string().merge(Lww),
162
+ /** The principal that authored the grant (attribution, on the ledger forever). */
163
+ grantedBy: t.string().merge(Lww),
164
+ /** Epoch-ms the grant was authored (caller-stamped). */
165
+ grantedAt: t.int().merge(Lww),
166
+ /** `active` | `revoked` — revocation is the law's kill switch for a key. */
167
+ status: t.enum(GRANT_STATUSES).merge(Lww),
168
+ });
169
+
170
+ /**
171
+ * CreationGrant — the narrower power to CREATE workspaces (the invite key,
172
+ * lawful edition). Same shape and same enforcement path as AdminGrant, but the
173
+ * worker honours it ONLY for `createWorkspace`-shaped access — separation of the
174
+ * "may invite tenants" power from the "may govern the cloud" power.
175
+ */
176
+ export const CreationGrant = aggregate("CreationGrant", {
177
+ /** sha256 hex of the creation bearer secret. */
178
+ keyHash: t.string().merge(Lww),
179
+ /** Human label for audit. */
180
+ label: t.string().merge(Lww),
181
+ /** The principal that authored the grant. */
182
+ grantedBy: t.string().merge(Lww),
183
+ /** Epoch-ms the grant was authored (caller-stamped). */
184
+ grantedAt: t.int().merge(Lww),
185
+ /** `active` | `revoked`. */
186
+ status: t.enum(GRANT_STATUSES).merge(Lww),
187
+ });
188
+
189
+ /**
190
+ * CloudPolicy — THE QUOTA LAW, a law-state singleton (id `cloud-policy:cloud`).
191
+ * Abuse prevention is LAW, not host config: every principal may hold at most
192
+ * `maxWorkspacesPerPrincipal` live (non-retired) workspaces, and every workspace
193
+ * ledger accepts at most `workspaceByteCap` cumulative pushed bytes. The escalation
194
+ * path from either limit is a QUOTA REQUEST: an admin authors {@link grantQuota}
195
+ * (more workspaces for one principal) or {@link setWorkspaceByteCap} (a bigger
196
+ * ledger for one workspace) — granted on the record, revocable by re-granting
197
+ * less. The worker is the bailiff: it counts and meters, the law decides.
198
+ */
199
+ export const CloudPolicy = aggregate("CloudPolicy", {
200
+ /** The singleton key — always `"cloud"`. */
201
+ scope: t.string().merge(Lww),
202
+ /** How many live workspaces one principal may hold (the default allowance). */
203
+ maxWorkspacesPerPrincipal: t.int().merge(Lww),
204
+ /** Cumulative pushed-bytes cap per workspace ledger (bytes). */
205
+ workspaceByteCap: t.int().merge(Lww),
206
+ /** Who last set the policy (attribution). */
207
+ setBy: t.string().merge(Lww),
208
+ /** Epoch-ms the policy was last set (caller-stamped). */
209
+ setAt: t.int().merge(Lww),
210
+ });
211
+
212
+ /**
213
+ * QuotaGrant — a granted quota request: one principal's workspace allowance,
214
+ * overriding the {@link CloudPolicy} default. The LATEST grant for a principal
215
+ * wins (raise by granting more, lower by granting less) — every change is an
216
+ * attributed, replayable intent.
217
+ */
218
+ export const QuotaGrant = aggregate("QuotaGrant", {
219
+ /** The auth-provider principal uid the grant is for. */
220
+ principal: t.string().merge(Lww),
221
+ /** The granted live-workspace allowance. */
222
+ maxWorkspaces: t.int().merge(Lww),
223
+ /** Who granted it (attribution, on the ledger forever). */
224
+ grantedBy: t.string().merge(Lww),
225
+ /** Epoch-ms the grant was authored (caller-stamped). */
226
+ grantedAt: t.int().merge(Lww),
227
+ });
228
+
229
+ /**
230
+ * PlatformGrant — the invite to BECOME A PLATFORM. Platform creation is
231
+ * invite-only: a principal may author {@link birthPlatform} iff an `active`
232
+ * PlatformGrant names their uid. Same grant/revoke discipline as Admin/Creation
233
+ * grants — authority is a law-state fact, never a worker config.
234
+ */
235
+ export const PlatformGrant = aggregate("PlatformGrant", {
236
+ /** The auth-provider principal uid invited to create platforms. */
237
+ principal: t.string().merge(Lww),
238
+ /** Human label for audit. */
239
+ label: t.string().merge(Lww),
240
+ /** Who granted it. */
241
+ grantedBy: t.string().merge(Lww),
242
+ /** Epoch-ms the grant was authored (caller-stamped). */
243
+ grantedAt: t.int().merge(Lww),
244
+ /** `active` | `revoked`. */
245
+ status: t.enum(GRANT_STATUSES).merge(Lww),
246
+ });
247
+
248
+ // --- workspace directives ---------------------------------------------------------
249
+
250
+ /**
251
+ * createWorkspace — record the lawful REQUEST for a workspace. Nomos MINTS the
252
+ * `CloudWorkspace` id (the payload carries none); the record is born
253
+ * `status:"requested"` with `ownerGrantHash:""` — no bearer exists until the
254
+ * worker provisions and authors {@link provisionWorkspace}.
255
+ */
256
+ export const createWorkspace = directive("createWorkspace")
257
+ .creates(CloudWorkspace)
258
+ .payload(
259
+ z.object({
260
+ name: z.string().min(1),
261
+ /** Hosting tier; defaults to the edge DO. */
262
+ tier: z.enum(WORKSPACE_TIERS).default("edge"),
263
+ /** Parent CloudWorkspace aggregate id; `""` (default) = root. */
264
+ parent: z.string().default(""),
265
+ /** The auth-provider principal uid the request claimed; `""` = unclaimed. */
266
+ principal: z.string().default(""),
267
+ requestedBy: z.string().min(1),
268
+ requestedAt: epochMs,
269
+ }),
270
+ )
271
+ .plan((p) => {
272
+ create(CloudWorkspace)
273
+ .set("name", p.name)
274
+ .set("parent", p.parent)
275
+ .set("principal", p.principal)
276
+ .set("tier", p.tier)
277
+ .set("status", "requested" as const)
278
+ .set("ownerGrantHash", "") // no owner credential until provisioned
279
+ .set("createdBy", p.requestedBy)
280
+ .set("createdAt", p.requestedAt);
281
+ return [];
282
+ });
283
+
284
+ /**
285
+ * birthCloud — THE CLOUD'S OWN BIRTH INTENT. Root authors this once, into its own
286
+ * chain, under this very law: the platform's `CloudWorkspace` record with
287
+ * `parent: ""` (the root of the world tree) and `principal` = the genesis
288
+ * auth-provider uid the whole tree rests on. Born `provisioned` — the cloud is
289
+ * alive by construction (it is authoring this very intent) — and with
290
+ * `ownerGrantHash: ""`: root is governed by AdminGrants, never an owner secret.
291
+ * Every later birth is parented (directly or transitively) to this record.
292
+ */
293
+ export const birthCloud = directive("birthCloud")
294
+ .creates(CloudWorkspace)
295
+ .payload(
296
+ z.object({
297
+ /** The genesis auth-provider principal uid upon which the world rests. */
298
+ principal: z.string().min(1),
299
+ name: z.string().min(1).default("root"),
300
+ tier: z.enum(WORKSPACE_TIERS).default("edge"),
301
+ bornAt: epochMs,
302
+ }),
303
+ )
304
+ .plan((p) => {
305
+ create(CloudWorkspace)
306
+ .set("name", p.name)
307
+ .set("parent", "") // the root of the world tree
308
+ .set("principal", p.principal)
309
+ .set("tier", p.tier)
310
+ .set("status", "provisioned" as const)
311
+ .set("ownerGrantHash", "") // root answers to AdminGrants, not an owner secret
312
+ .set("createdBy", p.principal)
313
+ .set("createdAt", p.bornAt)
314
+ .set("provisionedAt", p.bornAt);
315
+ return [];
316
+ });
317
+
318
+ /**
319
+ * provisionWorkspace — the worker's RETURN RECEIPT: authored AFTER it physically
320
+ * provisioned the Artifacts repo + booted the holon and minted the owner secret.
321
+ * Records sha256(ownerSecret) as the credential on file and flips the workspace
322
+ * to `provisioned`. The secret itself goes to the requester ONCE and dies
323
+ * everywhere else.
324
+ */
325
+ export const provisionWorkspace = directive("provisionWorkspace")
326
+ .mutates(CloudWorkspace)
327
+ .payload(
328
+ z.object({
329
+ workspaceId: z.string().min(1),
330
+ ownerGrantHash: sha256Hex,
331
+ provisionedAt: epochMs,
332
+ provisionedBy: z.string().min(1),
333
+ }),
334
+ )
335
+ .plan((p) => {
336
+ const ws = instance(CloudWorkspace, p.workspaceId);
337
+ return [
338
+ set(ws, "ownerGrantHash", p.ownerGrantHash),
339
+ set(ws, "provisionedAt", p.provisionedAt),
340
+ set(ws, "status", "provisioned" as const),
341
+ ];
342
+ });
343
+
344
+ /**
345
+ * rotateWorkspaceOwner — replace the owner credential ON THE RECORD. The old
346
+ * bearer stops verifying the instant this intent folds; nothing worker-side needs
347
+ * flushing because the worker never held the credential — only the law did.
348
+ */
349
+ export const rotateWorkspaceOwner = directive("rotateWorkspaceOwner")
350
+ .mutates(CloudWorkspace)
351
+ .payload(
352
+ z.object({
353
+ workspaceId: z.string().min(1),
354
+ ownerGrantHash: sha256Hex,
355
+ rotatedBy: z.string().min(1),
356
+ rotatedAt: epochMs,
357
+ }),
358
+ )
359
+ .plan((p) => {
360
+ const ws = instance(CloudWorkspace, p.workspaceId);
361
+ return [set(ws, "ownerGrantHash", p.ownerGrantHash)];
362
+ });
363
+
364
+ /**
365
+ * setWorkspaceTier — move a workspace between `edge` and `heavy` ON THE RECORD;
366
+ * the worker performs the (state-free — the ledger IS the workspace) re-mount to
367
+ * match the law.
368
+ */
369
+ export const setWorkspaceTier = directive("setWorkspaceTier")
370
+ .mutates(CloudWorkspace)
371
+ .payload(
372
+ z.object({
373
+ workspaceId: z.string().min(1),
374
+ tier: z.enum(WORKSPACE_TIERS),
375
+ changedBy: z.string().min(1),
376
+ changedAt: epochMs,
377
+ }),
378
+ )
379
+ .plan((p) => {
380
+ const ws = instance(CloudWorkspace, p.workspaceId);
381
+ return [set(ws, "tier", p.tier)];
382
+ });
383
+
384
+ /**
385
+ * retireWorkspace — the law withdraws the workspace. The worker thereafter
386
+ * refuses its bearers and may reclaim the machinery; the ledger (git custody)
387
+ * remains — retirement is a status, never an erasure.
388
+ */
389
+ export const retireWorkspace = directive("retireWorkspace")
390
+ .mutates(CloudWorkspace)
391
+ .payload(
392
+ z.object({
393
+ workspaceId: z.string().min(1),
394
+ retiredBy: z.string().min(1),
395
+ retiredAt: epochMs,
396
+ }),
397
+ )
398
+ .plan((p) => {
399
+ const ws = instance(CloudWorkspace, p.workspaceId);
400
+ return [set(ws, "status", "retired" as const)];
401
+ });
402
+
403
+ /**
404
+ * birthPlatform — A PLATFORM IS BORN: the cloud, one level down. Records the
405
+ * platform-kind workspace (parented to root, owned by the invited principal,
406
+ * carrying its POOL). The worker then provisions it exactly like the cloud
407
+ * provisioned itself: deploys the SAME governance law into it, seeds ITS founding
408
+ * AdminGrant, and the platform claims itself with its own birth intent on its own
409
+ * chain. Recursion, not new machinery.
410
+ */
411
+ export const birthPlatform = directive("birthPlatform")
412
+ .creates(CloudWorkspace)
413
+ .payload(
414
+ z.object({
415
+ name: z.string().min(1),
416
+ /** The auth-provider uid of the platform OWNER (must hold a PlatformGrant). */
417
+ principal: z.string().min(1),
418
+ /** Parent CloudWorkspace aggregate id (root's record). */
419
+ parent: z.string().default(""),
420
+ /** The pool: how many live children the platform may parent. */
421
+ pool: z.number().int().positive().default(50),
422
+ tier: z.enum(WORKSPACE_TIERS).default("edge"),
423
+ requestedBy: z.string().min(1),
424
+ requestedAt: epochMs,
425
+ }),
426
+ )
427
+ .plan((p) => {
428
+ create(CloudWorkspace)
429
+ .set("name", p.name)
430
+ .set("parent", p.parent)
431
+ .set("principal", p.principal)
432
+ .set("kind", "platform" as const)
433
+ .set("pool", p.pool)
434
+ .set("tier", p.tier)
435
+ .set("status", "requested" as const)
436
+ .set("ownerGrantHash", "")
437
+ .set("createdBy", p.requestedBy)
438
+ .set("createdAt", p.requestedAt);
439
+ return [];
440
+ });
441
+
442
+ /** setPlatformPool — the pool edition of a granted quota request. */
443
+ export const setPlatformPool = directive("setPlatformPool")
444
+ .mutates(CloudWorkspace)
445
+ .payload(
446
+ z.object({
447
+ workspaceId: z.string().min(1),
448
+ pool: z.number().int().positive(),
449
+ setBy: z.string().min(1),
450
+ setAt: epochMs,
451
+ }),
452
+ )
453
+ .plan((p) => {
454
+ const ws = instance(CloudWorkspace, p.workspaceId);
455
+ return [set(ws, "pool", p.pool)];
456
+ });
457
+
458
+ /**
459
+ * grantPlatformCreation / revokePlatformCreation — open and close the
460
+ * become-a-platform door for one principal (see {@link PlatformGrant}).
461
+ */
462
+ export const grantPlatformCreation = directive("grantPlatformCreation")
463
+ .creates(PlatformGrant)
464
+ .payload(
465
+ z.object({
466
+ principal: z.string().min(1),
467
+ label: z.string().min(1),
468
+ grantedBy: z.string().min(1),
469
+ grantedAt: epochMs,
470
+ }),
471
+ )
472
+ .plan((p) => {
473
+ create(PlatformGrant)
474
+ .set("principal", p.principal)
475
+ .set("label", p.label)
476
+ .set("grantedBy", p.grantedBy)
477
+ .set("grantedAt", p.grantedAt)
478
+ .set("status", "active" as const);
479
+ return [];
480
+ });
481
+
482
+ export const revokePlatformCreation = directive("revokePlatformCreation")
483
+ .mutates(PlatformGrant)
484
+ .payload(
485
+ z.object({
486
+ grantId: z.string().min(1),
487
+ revokedBy: z.string().min(1),
488
+ revokedAt: epochMs,
489
+ }),
490
+ )
491
+ .plan((p) => {
492
+ const grant = instance(PlatformGrant, p.grantId);
493
+ return [set(grant, "status", "revoked" as const)];
494
+ });
495
+
496
+ /**
497
+ * AuthProvider — BYOAuth: WHO VOUCHES FOR THIS SUBTREE'S PRINCIPALS. A law-state
498
+ * singleton (id `auth-provider:platform`) in a PLATFORM's own law: the OIDC-style
499
+ * issuer + public JWKS URL of the platform's identity provider. Once set, births
500
+ * under the platform verify end-user tokens against THIS provider (asymmetric
501
+ * keys only — a BYO provider proves possession with signatures, never shared
502
+ * secrets). The trust boundary is the subtree: a platform's provider speaks for
503
+ * principals only WITHIN that platform's own tree. The cloud's own provider
504
+ * (captain app) is the depth-0 case, configured by the host.
505
+ */
506
+ export const AuthProvider = aggregate("AuthProvider", {
507
+ /** The singleton key — always `"platform"`. */
508
+ scope: t.string().merge(Lww),
509
+ /** The token issuer (the `iss` claim tokens must carry). */
510
+ issuer: t.string().merge(Lww),
511
+ /** The provider's public JWKS endpoint (asymmetric verification keys). */
512
+ jwksUrl: t.string().merge(Lww),
513
+ /** Human label for audit ("acme supabase", ...). */
514
+ label: t.string().merge(Lww),
515
+ /** Who set it (attribution). */
516
+ setBy: t.string().merge(Lww),
517
+ /** Epoch-ms it was set (caller-stamped). */
518
+ setAt: t.int().merge(Lww),
519
+ });
520
+
521
+ /**
522
+ * setAuthProvider — declare (or amend) the platform's identity provider. An
523
+ * Ensure on the singleton; every change is an attributed, replayable intent.
524
+ */
525
+ export const setAuthProvider = directive("setAuthProvider")
526
+ .ensures(AuthProvider)
527
+ .payload(
528
+ z.object({
529
+ // NOT z.url(): zod's url() needs the URL global, which the sealed
530
+ // deterministic engine does not provide — a regex keeps the plan pure.
531
+ issuer: z.string().regex(/^https?:\/\/\S+$/, "expected an http(s) URL"),
532
+ jwksUrl: z.string().regex(/^https?:\/\/\S+$/, "expected an http(s) URL"),
533
+ label: z.string().min(1),
534
+ setBy: z.string().min(1),
535
+ setAt: epochMs,
536
+ }),
537
+ )
538
+ .plan((p) => {
539
+ const ap = instance(AuthProvider, "auth-provider:platform");
540
+ return [
541
+ withMarker(set(ap, "scope", "platform"), "ensures"),
542
+ set(ap, "issuer", p.issuer),
543
+ set(ap, "jwksUrl", p.jwksUrl),
544
+ set(ap, "label", p.label),
545
+ set(ap, "setBy", p.setBy),
546
+ set(ap, "setAt", p.setAt),
547
+ ];
548
+ });
549
+
550
+ /**
551
+ * HostnameClaim — a CUSTOM HOSTNAME bound to a platform: `api.acme.com` serving
552
+ * acme's subtree. A root-custody fact (the hostname is the HOST's edge resource —
553
+ * certs, routing — so root records who holds it); first claim wins, collisions
554
+ * refuse, release frees the name. The router resolves Host → claim → the
555
+ * platform's namespace.
556
+ */
557
+ export const HostnameClaim = aggregate("HostnameClaim", {
558
+ /** The fully-qualified hostname (lowercase). */
559
+ hostname: t.string().merge(Lww),
560
+ /** The platform's CloudWorkspace aggregate id. */
561
+ workspaceId: t.string().merge(Lww),
562
+ /** The platform's workspace name (the `p--` namespace the router rewrites into). */
563
+ platform: t.string().merge(Lww),
564
+ /** The principal that claimed it. */
565
+ claimedBy: t.string().merge(Lww),
566
+ /** Epoch-ms of the claim (caller-stamped). */
567
+ claimedAt: t.int().merge(Lww),
568
+ /** `active` | `released`. */
569
+ status: t.enum(["active", "released"]).merge(Lww),
570
+ });
571
+
572
+ /** claimHostname — bind a hostname to a platform (worker-authored after the edge accepts it). */
573
+ export const claimHostname = directive("claimHostname")
574
+ .creates(HostnameClaim)
575
+ .payload(
576
+ z.object({
577
+ hostname: z.string().regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$/, "expected a lowercase FQDN"),
578
+ workspaceId: z.string().min(1),
579
+ platform: z.string().min(1),
580
+ claimedBy: z.string().min(1),
581
+ claimedAt: epochMs,
582
+ }),
583
+ )
584
+ .plan((p) => {
585
+ create(HostnameClaim)
586
+ .set("hostname", p.hostname)
587
+ .set("workspaceId", p.workspaceId)
588
+ .set("platform", p.platform)
589
+ .set("claimedBy", p.claimedBy)
590
+ .set("claimedAt", p.claimedAt)
591
+ .set("status", "active" as const);
592
+ return [];
593
+ });
594
+
595
+ /** releaseHostname — free the name (the record stays — audit, never erasure). */
596
+ export const releaseHostname = directive("releaseHostname")
597
+ .mutates(HostnameClaim)
598
+ .payload(
599
+ z.object({
600
+ claimId: z.string().min(1),
601
+ releasedBy: z.string().min(1),
602
+ releasedAt: epochMs,
603
+ }),
604
+ )
605
+ .plan((p) => {
606
+ const c = instance(HostnameClaim, p.claimId);
607
+ return [set(c, "status", "released" as const)];
608
+ });
609
+
610
+ /**
611
+ * setCloudPolicy — set (or amend) THE QUOTA LAW. An Ensure on the law-state
612
+ * singleton: the first author births it, later authors amend it in place —
613
+ * every change attributed and replayable.
614
+ */
615
+ export const setCloudPolicy = directive("setCloudPolicy")
616
+ .ensures(CloudPolicy)
617
+ .payload(
618
+ z.object({
619
+ maxWorkspacesPerPrincipal: z.number().int().positive(),
620
+ workspaceByteCap: z.number().int().positive(),
621
+ setBy: z.string().min(1),
622
+ setAt: epochMs,
623
+ }),
624
+ )
625
+ .plan((p) => {
626
+ const pol = instance(CloudPolicy, "cloud-policy:cloud");
627
+ return [
628
+ withMarker(set(pol, "scope", "cloud"), "ensures"),
629
+ set(pol, "maxWorkspacesPerPrincipal", p.maxWorkspacesPerPrincipal),
630
+ set(pol, "workspaceByteCap", p.workspaceByteCap),
631
+ set(pol, "setBy", p.setBy),
632
+ set(pol, "setAt", p.setAt),
633
+ ];
634
+ });
635
+
636
+ /**
637
+ * grantQuota — grant a quota request: a principal's workspace allowance. The
638
+ * latest grant for the principal is the one in force.
639
+ */
640
+ export const grantQuota = directive("grantQuota")
641
+ .creates(QuotaGrant)
642
+ .payload(
643
+ z.object({
644
+ principal: z.string().min(1),
645
+ maxWorkspaces: z.number().int().positive(),
646
+ grantedBy: z.string().min(1),
647
+ grantedAt: epochMs,
648
+ }),
649
+ )
650
+ .plan((p) => {
651
+ create(QuotaGrant)
652
+ .set("principal", p.principal)
653
+ .set("maxWorkspaces", p.maxWorkspaces)
654
+ .set("grantedBy", p.grantedBy)
655
+ .set("grantedAt", p.grantedAt);
656
+ return [];
657
+ });
658
+
659
+ /**
660
+ * setWorkspaceByteCap — grant one workspace a bigger (or smaller) ledger than the
661
+ * {@link CloudPolicy} default: the byte-cap edition of a granted quota request.
662
+ */
663
+ export const setWorkspaceByteCap = directive("setWorkspaceByteCap")
664
+ .mutates(CloudWorkspace)
665
+ .payload(
666
+ z.object({
667
+ workspaceId: z.string().min(1),
668
+ byteCap: z.number().int().positive(),
669
+ setBy: z.string().min(1),
670
+ setAt: epochMs,
671
+ }),
672
+ )
673
+ .plan((p) => {
674
+ const ws = instance(CloudWorkspace, p.workspaceId);
675
+ return [set(ws, "byteCap", p.byteCap)];
676
+ });
677
+
678
+ // --- grant directives ---------------------------------------------------------------
679
+
680
+ /**
681
+ * grantAdmin — mint an admin credential record (`status:"active"`). Genesis
682
+ * authors the FIRST one from the bootstrap env var — which is then spent forever;
683
+ * every later grant is an admin granting, attributed and admitted under this law.
684
+ */
685
+ export const grantAdmin = directive("grantAdmin")
686
+ .creates(AdminGrant)
687
+ .payload(
688
+ z.object({
689
+ keyHash: sha256Hex,
690
+ label: z.string().min(1),
691
+ grantedBy: z.string().min(1),
692
+ grantedAt: epochMs,
693
+ }),
694
+ )
695
+ .plan((p) => {
696
+ create(AdminGrant)
697
+ .set("keyHash", p.keyHash)
698
+ .set("label", p.label)
699
+ .set("grantedBy", p.grantedBy)
700
+ .set("grantedAt", p.grantedAt)
701
+ .set("status", "active" as const);
702
+ return [];
703
+ });
704
+
705
+ /**
706
+ * revokeAdmin — flip an AdminGrant to `revoked`. The key stops verifying at fold
707
+ * time; the grant record (who granted it, when, who killed it) stays on the
708
+ * ledger — audit is structural, not a log file.
709
+ */
710
+ export const revokeAdmin = directive("revokeAdmin")
711
+ .mutates(AdminGrant)
712
+ .payload(
713
+ z.object({
714
+ grantId: z.string().min(1),
715
+ revokedBy: z.string().min(1),
716
+ revokedAt: epochMs,
717
+ }),
718
+ )
719
+ .plan((p) => {
720
+ const grant = instance(AdminGrant, p.grantId);
721
+ return [set(grant, "status", "revoked" as const)];
722
+ });
723
+
724
+ /**
725
+ * grantCreation — mint a workspace-creation credential record (`status:"active"`).
726
+ * The lawful replacement for the `NOMOS_CLOUD_INVITE_KEY` env var: who may invite
727
+ * tenants is law state, grantable and revocable on the record.
728
+ */
729
+ export const grantCreation = directive("grantCreation")
730
+ .creates(CreationGrant)
731
+ .payload(
732
+ z.object({
733
+ keyHash: sha256Hex,
734
+ label: z.string().min(1),
735
+ grantedBy: z.string().min(1),
736
+ grantedAt: epochMs,
737
+ }),
738
+ )
739
+ .plan((p) => {
740
+ create(CreationGrant)
741
+ .set("keyHash", p.keyHash)
742
+ .set("label", p.label)
743
+ .set("grantedBy", p.grantedBy)
744
+ .set("grantedAt", p.grantedAt)
745
+ .set("status", "active" as const);
746
+ return [];
747
+ });
748
+
749
+ /** revokeCreation — flip a CreationGrant to `revoked` (see {@link revokeAdmin}). */
750
+ export const revokeCreation = directive("revokeCreation")
751
+ .mutates(CreationGrant)
752
+ .payload(
753
+ z.object({
754
+ grantId: z.string().min(1),
755
+ revokedBy: z.string().min(1),
756
+ revokedAt: epochMs,
757
+ }),
758
+ )
759
+ .plan((p) => {
760
+ const grant = instance(CreationGrant, p.grantId);
761
+ return [set(grant, "status", "revoked" as const)];
762
+ });
763
+
764
+ // --- declared read queries (the worker's ENTIRE enforcement surface) -----------------
765
+ //
766
+ // Auto-discovered by nomos-compile; each is an INDEXED probe (never a scan) the
767
+ // worker fires on the hot auth path. These four lookups are the whole interface
768
+ // between machinery and law.
769
+
770
+ /** Resolve a workspace by its unique name (the `:ws` URL segment → the law record). */
771
+ export const workspaceByName = query("workspaceByName").key("name").returns(CloudWorkspace);
772
+
773
+ /** "Is this bearer an admin?" — probe by sha256(bearer); active grant = yes. */
774
+ export const adminGrantByKeyHash = query("adminGrantByKeyHash")
775
+ .key("keyHash")
776
+ .returns(AdminGrant);
777
+
778
+ /** "May this bearer create workspaces?" — probe by sha256(bearer). */
779
+ export const creationGrantByKeyHash = query("creationGrantByKeyHash")
780
+ .key("keyHash")
781
+ .returns(CreationGrant);
782
+
783
+ /** All children of a workspace (`""` = the roots) — the workspace tree's read side. */
784
+ export const workspacesByParent = query("workspacesByParent")
785
+ .key("parent")
786
+ .returns(CloudWorkspace);
787
+
788
+ /** One principal's workspaces — the quota gate counts the non-retired ones. */
789
+ export const workspacesByPrincipal = query("workspacesByPrincipal")
790
+ .key("principal")
791
+ .returns(CloudWorkspace);
792
+
793
+ /** THE QUOTA LAW singleton (`scope: "cloud"`) — defaults for allowance + byte cap. */
794
+ export const cloudPolicy = query("cloudPolicy").key("scope").returns(CloudPolicy);
795
+
796
+ /** A principal's quota grants — the LATEST one is the allowance in force. */
797
+ export const quotaByPrincipal = query("quotaByPrincipal")
798
+ .key("principal")
799
+ .returns(QuotaGrant);
800
+
801
+ /** "May this principal create platforms?" — invite-only; active grant = yes. */
802
+ export const platformGrantByPrincipal = query("platformGrantByPrincipal")
803
+ .key("principal")
804
+ .returns(PlatformGrant);
805
+
806
+ /** The platform's identity provider (BYOAuth) — `scope: "platform"` singleton. */
807
+ export const authProvider = query("authProvider").key("scope").returns(AuthProvider);
808
+
809
+ /** Host → platform: the router's resolver (active claim = the hostname serves). */
810
+ export const hostnameClaimByHostname = query("hostnameClaimByHostname")
811
+ .key("hostname")
812
+ .returns(HostnameClaim);
813
+
814
+ /** A platform's hostnames — the list side (key = the platform's record id). */
815
+ export const hostnameClaimsByWorkspace = query("hostnameClaimsByWorkspace")
816
+ .key("workspaceId")
817
+ .returns(HostnameClaim);