@githolon/dsl 0.94.2 → 0.95.1

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": "@githolon/dsl",
3
- "version": "0.94.2",
3
+ "version": "0.95.1",
4
4
  "type": "module",
5
5
  "description": "Nomos 2 domain-authoring DSL: aggregates + directives in TS, executed and encoded to the Rust kernel's wire shapes.",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -322,6 +322,18 @@ export const enrollFirstDevice = directive("enrollFirstDevice")
322
322
  /** THE CAPTURED PREMISE: the IdP's signed identity assertion (JWT), re-verified on every lane against
323
323
  * the on-chain AuthProvider keys. */
324
324
  idpToken: z.string().min(1),
325
+ /** THE KEYLESS DELEGATION CERT (JSON `executor::birth_cert::BirthCert`) — the self-serve sibling of
326
+ * `enrollDelegation.certJson`. Built CLIENT-SIDE via the `cert_sign` op: DEVICE-self-signed by this
327
+ * same device key `P_U` (parent_key == P_U), founder == `user:<uid>`, carrying `verifiedVia` +
328
+ * `idpToken` + `capturedClock`. There is NO tenant `S_P` in the loop — the kernel's home-birth chain
329
+ * walk (`verify_to_root`, keyless branch) RE-VERIFIES the token against the platform-attested
330
+ * AuthProvider (bound to K_root by the terminal platform_cert), so a forged/swapped cert fails the
331
+ * child's own gate. Writing it as the user's `SignerDelegation` is what lets `birthHome`'s offer-effect
332
+ * assemble a WARRANTED travelling chain (closes co2's `birth-cert-not-seeded` / empty signerDelegation).
333
+ * OPTIONAL — an enroll-only flow (seat the signer, no imminent home birth) omits it and seeds no
334
+ * delegation (backward-compatible with every pre-B `enrollFirstDevice` caller). The keyless home-birth
335
+ * ceremony ALWAYS supplies it (that is what seeds the delegation the chain needs). */
336
+ delegationCert: z.string().min(1).optional(),
325
337
  }),
326
338
  )
327
339
  .plan((p, ctx) => {
@@ -329,7 +341,8 @@ export const enrollFirstDevice = directive("enrollFirstDevice")
329
341
  // evidence — the framework may; an author cannot). The kernel arm proves the principal is the IdP subject.
330
342
  const me = ctx.principal().asAuthoritySubject<string>("bootstrap my first device signer key from a verified IdP token");
331
343
  const rawPrincipal = endorsementOf(me)?.principal ?? "";
332
- return writeTuple({
344
+ // (1) seat the signer leaf (the RelationTuple — this directive's primary `.ensures`).
345
+ const tupleOps = writeTuple({
333
346
  object: signerObject(rawPrincipal),
334
347
  relation: SIGNER_RELATION,
335
348
  subject: "key:" + p.keyHash,
@@ -338,6 +351,22 @@ export const enrollFirstDevice = directive("enrollFirstDevice")
338
351
  verifiedVia: p.verifiedVia,
339
352
  validFromEpoch: p.validFromEpoch,
340
353
  });
354
+ // (2) fold the KEYLESS delegation cert as the user's `SignerDelegation` singleton (a SECONDARY ensures,
355
+ // per-op marked — the id is deterministic-by-user, an upsert). This is the seed `birthHome` reads to
356
+ // assemble the warranted chain; without it the home is born headless (co2's block).
357
+ // The delegation is keyed by the AUTHENTICATED principal — EXACTLY the `founder` the kernel's birth
358
+ // offer-effect reads it back by (`read_signer_delegation(state, &founder)`, founder == captured principal
359
+ // == this `rawPrincipal`, already in `user:<uid>` form). Do NOT re-prefix.
360
+ // Absent delegationCert ⇒ enroll-only (no delegation seeded), byte-identical to a pre-B enroll.
361
+ if (!p.delegationCert) return tupleOps;
362
+ const d = instance(SignerDelegation, signerDelegationInstanceId(rawPrincipal));
363
+ const delegationOps: PlannedOp[] = [
364
+ withMarker(set(d, "user", rawPrincipal), "ensures"),
365
+ withMarker(set(d, "deviceKey", "key:" + p.keyHash), "ensures"),
366
+ withMarker(set(d, "certJson", p.delegationCert), "ensures"),
367
+ withMarker(set(d, "enrolledAt", p.grantedAt), "ensures"),
368
+ ];
369
+ return [...tupleOps, ...delegationOps];
341
370
  })
342
371
  // THE KEYLESS GATE DECLARATION: the carried device-bound `idpToken` IS this directive's authorization
343
372
  // (re-verified against the workspace AuthProvider on every lane), not a pre-enrolled signer. This lowers