@ottochain/sdk 2.4.0 → 2.6.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 (227) hide show
  1. package/dist/cjs/apps/compute/index.js +33 -0
  2. package/dist/cjs/apps/compute/state-machines/compute-rule110.js +164 -0
  3. package/dist/cjs/apps/compute/state-machines/index.js +9 -0
  4. package/dist/cjs/apps/contracts/index.js +1 -1
  5. package/dist/cjs/apps/contracts/state-machines/contract-agreement.js +126 -148
  6. package/dist/cjs/apps/contracts/state-machines/contract-escrow.js +153 -174
  7. package/dist/cjs/apps/contracts/state-machines/contract-universal.js +46 -58
  8. package/dist/cjs/apps/corporate/state-machines/corp-board.js +415 -481
  9. package/dist/cjs/apps/corporate/state-machines/corp-entity.js +368 -440
  10. package/dist/cjs/apps/corporate/state-machines/corp-securities.js +532 -647
  11. package/dist/cjs/apps/corporate/state-machines/corp-shareholders.js +499 -603
  12. package/dist/cjs/apps/governance/index.js +7 -7
  13. package/dist/cjs/apps/governance/state-machines/dao-multisig.js +170 -209
  14. package/dist/cjs/apps/governance/state-machines/dao-reputation.js +161 -214
  15. package/dist/cjs/apps/governance/state-machines/dao-single.js +92 -92
  16. package/dist/cjs/apps/governance/state-machines/dao-token.js +169 -223
  17. package/dist/cjs/apps/governance/state-machines/governance-simple.js +185 -217
  18. package/dist/cjs/apps/governance/state-machines/governance-universal.js +64 -64
  19. package/dist/cjs/apps/identity/constants.js +16 -24
  20. package/dist/cjs/apps/identity/index.js +1 -1
  21. package/dist/cjs/apps/identity/state-machines/identity-agent.js +124 -158
  22. package/dist/cjs/apps/identity/state-machines/identity-oracle.js +151 -169
  23. package/dist/cjs/apps/identity/state-machines/identity-registry.js +89 -115
  24. package/dist/cjs/apps/identity/state-machines/identity-universal.js +51 -57
  25. package/dist/cjs/apps/index.js +4 -1
  26. package/dist/cjs/apps/lending/assets.js +41 -17
  27. package/dist/cjs/apps/lending/credit-scoring.js +4 -4
  28. package/dist/cjs/apps/lending/eligibility.js +9 -25
  29. package/dist/cjs/apps/lending/index.js +1 -1
  30. package/dist/cjs/apps/lending/state-machines/lending-zk-loan.js +177 -156
  31. package/dist/cjs/apps/markets/index.js +1 -1
  32. package/dist/cjs/apps/markets/state-machines/market-auction.js +115 -134
  33. package/dist/cjs/apps/markets/state-machines/market-crowdfund.js +122 -137
  34. package/dist/cjs/apps/markets/state-machines/market-group-buy.js +158 -177
  35. package/dist/cjs/apps/markets/state-machines/market-prediction.js +193 -227
  36. package/dist/cjs/apps/markets/state-machines/market-universal.js +65 -80
  37. package/dist/cjs/apps/oracles/index.js +1 -1
  38. package/dist/cjs/apps/privacy/index.js +67 -0
  39. package/dist/cjs/apps/privacy/state-machines/index.js +17 -0
  40. package/dist/cjs/apps/privacy/state-machines/mixer-ddhRing.js +286 -0
  41. package/dist/cjs/apps/privacy/state-machines/note-pool.js +476 -0
  42. package/dist/cjs/apps/staked-pool/assets.js +103 -0
  43. package/dist/cjs/apps/staked-pool/base.js +498 -0
  44. package/dist/cjs/apps/staked-pool/consumer.js +55 -0
  45. package/dist/cjs/apps/staked-pool/index.js +83 -0
  46. package/dist/cjs/apps/staked-pool/state-machines/index.js +12 -0
  47. package/dist/cjs/apps/staked-pool/state-machines/staked-pool-base.js +49 -0
  48. package/dist/cjs/apps/staked-pool/state-machines/staked-pool-oracle.js +131 -0
  49. package/dist/cjs/generated/google/protobuf/struct.js +1 -1
  50. package/dist/cjs/generated/google/protobuf/timestamp.js +1 -1
  51. package/dist/cjs/generated/ottochain/apps/contracts/v1/contract.js +1 -1
  52. package/dist/cjs/generated/ottochain/apps/corporate/v1/corporate.js +1 -1
  53. package/dist/cjs/generated/ottochain/apps/governance/v1/governance.js +1 -1
  54. package/dist/cjs/generated/ottochain/apps/identity/v1/attestation.js +1 -1
  55. package/dist/cjs/generated/ottochain/apps/identity/v1/identity.js +1 -1
  56. package/dist/cjs/generated/ottochain/apps/markets/v1/market.js +1 -1
  57. package/dist/cjs/generated/ottochain/v1/common.js +1 -1
  58. package/dist/cjs/generated/ottochain/v1/fiber.js +40 -2
  59. package/dist/cjs/generated/ottochain/v1/messages.js +1 -1
  60. package/dist/cjs/generated/ottochain/v1/records.js +1 -1
  61. package/dist/cjs/index.js +21 -3
  62. package/dist/cjs/ottochain/genesis-manifest.js +6 -0
  63. package/dist/cjs/ottochain/metagraph-client.js +63 -11
  64. package/dist/cjs/ottochain/snapshot.js +2 -4
  65. package/dist/cjs/ottochain/transaction.js +10 -0
  66. package/dist/cjs/privacy/sealed-bid.js +85 -82
  67. package/dist/cjs/privacy/shield-app.js +32 -32
  68. package/dist/cjs/schema/effects.js +145 -1
  69. package/dist/cjs/schema/fiber-app.js +139 -5
  70. package/dist/cjs/schema/guard-lint.js +3 -12
  71. package/dist/cjs/schema/guards.js +38 -38
  72. package/dist/cjs/templates/asset-policy.js +190 -0
  73. package/dist/cjs/templates/index.js +86 -0
  74. package/dist/cjs/templates/machine.js +130 -0
  75. package/dist/cjs/templates/migration.js +39 -0
  76. package/dist/cjs/templates/state-shape.js +38 -0
  77. package/dist/cjs/validation.js +1 -3
  78. package/dist/esm/apps/compute/index.js +29 -0
  79. package/dist/esm/apps/compute/state-machines/compute-rule110.js +161 -0
  80. package/dist/esm/apps/compute/state-machines/index.js +5 -0
  81. package/dist/esm/apps/contracts/index.js +4 -4
  82. package/dist/esm/apps/contracts/state-machines/contract-agreement.js +128 -150
  83. package/dist/esm/apps/contracts/state-machines/contract-escrow.js +155 -176
  84. package/dist/esm/apps/contracts/state-machines/contract-universal.js +47 -59
  85. package/dist/esm/apps/corporate/index.js +2 -2
  86. package/dist/esm/apps/corporate/state-machines/corp-board.js +418 -484
  87. package/dist/esm/apps/corporate/state-machines/corp-entity.js +371 -443
  88. package/dist/esm/apps/corporate/state-machines/corp-securities.js +535 -650
  89. package/dist/esm/apps/corporate/state-machines/corp-shareholders.js +502 -606
  90. package/dist/esm/apps/governance/index.js +10 -10
  91. package/dist/esm/apps/governance/state-machines/dao-multisig.js +172 -211
  92. package/dist/esm/apps/governance/state-machines/dao-reputation.js +163 -216
  93. package/dist/esm/apps/governance/state-machines/dao-single.js +94 -94
  94. package/dist/esm/apps/governance/state-machines/dao-token.js +171 -225
  95. package/dist/esm/apps/governance/state-machines/governance-simple.js +187 -219
  96. package/dist/esm/apps/governance/state-machines/governance-universal.js +65 -65
  97. package/dist/esm/apps/identity/constants.js +18 -26
  98. package/dist/esm/apps/identity/index.js +8 -8
  99. package/dist/esm/apps/identity/state-machines/identity-agent.js +125 -159
  100. package/dist/esm/apps/identity/state-machines/identity-oracle.js +153 -171
  101. package/dist/esm/apps/identity/state-machines/identity-registry.js +91 -117
  102. package/dist/esm/apps/identity/state-machines/identity-universal.js +52 -58
  103. package/dist/esm/apps/index.js +9 -6
  104. package/dist/esm/apps/lending/assets.js +41 -17
  105. package/dist/esm/apps/lending/credit-scoring.js +6 -6
  106. package/dist/esm/apps/lending/eligibility.js +10 -26
  107. package/dist/esm/apps/lending/index.js +5 -5
  108. package/dist/esm/apps/lending/state-machines/lending-zk-loan.js +178 -157
  109. package/dist/esm/apps/markets/index.js +5 -5
  110. package/dist/esm/apps/markets/state-machines/market-auction.js +117 -136
  111. package/dist/esm/apps/markets/state-machines/market-crowdfund.js +124 -139
  112. package/dist/esm/apps/markets/state-machines/market-group-buy.js +160 -179
  113. package/dist/esm/apps/markets/state-machines/market-prediction.js +195 -229
  114. package/dist/esm/apps/markets/state-machines/market-universal.js +66 -81
  115. package/dist/esm/apps/oracles/index.js +3 -3
  116. package/dist/esm/apps/privacy/index.js +56 -0
  117. package/dist/esm/apps/privacy/state-machines/index.js +6 -0
  118. package/dist/esm/apps/privacy/state-machines/mixer-ddhRing.js +282 -0
  119. package/dist/esm/apps/privacy/state-machines/note-pool.js +470 -0
  120. package/dist/esm/apps/staked-pool/assets.js +91 -0
  121. package/dist/esm/apps/staked-pool/base.js +493 -0
  122. package/dist/esm/apps/staked-pool/consumer.js +49 -0
  123. package/dist/esm/apps/staked-pool/index.js +60 -0
  124. package/dist/esm/apps/staked-pool/state-machines/index.js +6 -0
  125. package/dist/esm/apps/staked-pool/state-machines/staked-pool-base.js +46 -0
  126. package/dist/esm/apps/staked-pool/state-machines/staked-pool-oracle.js +127 -0
  127. package/dist/esm/generated/google/protobuf/struct.js +1 -1
  128. package/dist/esm/generated/google/protobuf/timestamp.js +1 -1
  129. package/dist/esm/generated/ottochain/apps/contracts/v1/contract.js +1 -1
  130. package/dist/esm/generated/ottochain/apps/corporate/v1/corporate.js +1 -1
  131. package/dist/esm/generated/ottochain/apps/governance/v1/governance.js +1 -1
  132. package/dist/esm/generated/ottochain/apps/identity/v1/attestation.js +1 -1
  133. package/dist/esm/generated/ottochain/apps/identity/v1/identity.js +1 -1
  134. package/dist/esm/generated/ottochain/apps/markets/v1/market.js +1 -1
  135. package/dist/esm/generated/ottochain/v1/common.js +1 -1
  136. package/dist/esm/generated/ottochain/v1/fiber.js +40 -2
  137. package/dist/esm/generated/ottochain/v1/messages.js +1 -1
  138. package/dist/esm/generated/ottochain/v1/records.js +1 -1
  139. package/dist/esm/index.js +10 -4
  140. package/dist/esm/ottochain/genesis-manifest.js +6 -0
  141. package/dist/esm/ottochain/metagraph-client.js +63 -11
  142. package/dist/esm/ottochain/snapshot.js +2 -4
  143. package/dist/esm/ottochain/transaction.js +8 -0
  144. package/dist/esm/privacy/index.js +2 -2
  145. package/dist/esm/privacy/sealed-bid.js +87 -84
  146. package/dist/esm/privacy/shield-app.js +33 -33
  147. package/dist/esm/schema/effects.js +137 -0
  148. package/dist/esm/schema/fiber-app.js +134 -5
  149. package/dist/esm/schema/guard-lint.js +3 -12
  150. package/dist/esm/schema/guards.js +36 -37
  151. package/dist/esm/templates/asset-policy.js +182 -0
  152. package/dist/esm/templates/index.js +41 -0
  153. package/dist/esm/templates/machine.js +125 -0
  154. package/dist/esm/templates/migration.js +34 -0
  155. package/dist/esm/templates/state-shape.js +34 -0
  156. package/dist/esm/validation.js +1 -3
  157. package/dist/esm/zk/index.js +4 -4
  158. package/dist/types/apps/compute/index.d.ts +176 -0
  159. package/dist/types/apps/compute/state-machines/compute-rule110.d.ts +157 -0
  160. package/dist/types/apps/compute/state-machines/index.d.ts +5 -0
  161. package/dist/types/apps/contracts/index.d.ts +14 -14
  162. package/dist/types/apps/contracts/state-machines/contract-agreement.d.ts +3 -3
  163. package/dist/types/apps/contracts/state-machines/contract-escrow.d.ts +3 -3
  164. package/dist/types/apps/contracts/state-machines/contract-universal.d.ts +4 -4
  165. package/dist/types/apps/corporate/index.d.ts +162 -162
  166. package/dist/types/apps/corporate/state-machines/corp-board.d.ts +88 -88
  167. package/dist/types/apps/corporate/state-machines/corp-entity.d.ts +14 -14
  168. package/dist/types/apps/corporate/state-machines/corp-securities.d.ts +18 -18
  169. package/dist/types/apps/corporate/state-machines/corp-shareholders.d.ts +43 -43
  170. package/dist/types/apps/governance/index.d.ts +81 -81
  171. package/dist/types/apps/governance/state-machines/dao-multisig.d.ts +16 -16
  172. package/dist/types/apps/governance/state-machines/dao-reputation.d.ts +22 -22
  173. package/dist/types/apps/governance/state-machines/dao-token.d.ts +21 -21
  174. package/dist/types/apps/governance/state-machines/governance-simple.d.ts +11 -11
  175. package/dist/types/apps/governance/state-machines/governance-universal.d.ts +4 -4
  176. package/dist/types/apps/identity/constants.d.ts +2 -2
  177. package/dist/types/apps/identity/index.d.ts +70 -70
  178. package/dist/types/apps/identity/state-machines/identity-agent.d.ts +23 -23
  179. package/dist/types/apps/identity/state-machines/identity-oracle.d.ts +11 -11
  180. package/dist/types/apps/identity/state-machines/identity-registry.d.ts +27 -27
  181. package/dist/types/apps/identity/state-machines/identity-universal.d.ts +4 -4
  182. package/dist/types/apps/index.d.ts +9 -6
  183. package/dist/types/apps/lending/assets.d.ts +2 -2
  184. package/dist/types/apps/lending/credit-scoring.d.ts +5 -5
  185. package/dist/types/apps/lending/eligibility.d.ts +2 -2
  186. package/dist/types/apps/lending/index.d.ts +20 -12
  187. package/dist/types/apps/lending/state-machines/lending-zk-loan.d.ts +15 -7
  188. package/dist/types/apps/markets/index.d.ts +76 -76
  189. package/dist/types/apps/markets/state-machines/market-auction.d.ts +12 -12
  190. package/dist/types/apps/markets/state-machines/market-crowdfund.d.ts +19 -19
  191. package/dist/types/apps/markets/state-machines/market-group-buy.d.ts +18 -18
  192. package/dist/types/apps/markets/state-machines/market-prediction.d.ts +15 -15
  193. package/dist/types/apps/markets/state-machines/market-universal.d.ts +7 -7
  194. package/dist/types/apps/oracles/index.d.ts +1 -1
  195. package/dist/types/apps/privacy/index.d.ts +328 -0
  196. package/dist/types/apps/privacy/state-machines/index.d.ts +6 -0
  197. package/dist/types/apps/privacy/state-machines/mixer-ddhRing.d.ts +337 -0
  198. package/dist/types/apps/privacy/state-machines/note-pool.d.ts +196 -0
  199. package/dist/types/apps/staked-pool/assets.d.ts +53 -0
  200. package/dist/types/apps/staked-pool/base.d.ts +80 -0
  201. package/dist/types/apps/staked-pool/consumer.d.ts +29 -0
  202. package/dist/types/apps/staked-pool/index.d.ts +51 -0
  203. package/dist/types/apps/staked-pool/state-machines/index.d.ts +6 -0
  204. package/dist/types/apps/staked-pool/state-machines/staked-pool-base.d.ts +8 -0
  205. package/dist/types/apps/staked-pool/state-machines/staked-pool-oracle.d.ts +34 -0
  206. package/dist/types/generated/openapi.d.ts +13 -0
  207. package/dist/types/generated/ottochain/v1/fiber.d.ts +7 -0
  208. package/dist/types/index.d.ts +3 -3
  209. package/dist/types/openapi.d.ts +4 -2
  210. package/dist/types/ottochain/genesis-manifest.d.ts +6 -0
  211. package/dist/types/ottochain/index.d.ts +1 -1
  212. package/dist/types/ottochain/metagraph-client.d.ts +69 -15
  213. package/dist/types/ottochain/transaction.d.ts +9 -1
  214. package/dist/types/ottochain/types.d.ts +1 -1
  215. package/dist/types/privacy/index.d.ts +2 -2
  216. package/dist/types/privacy/sealed-bid.d.ts +9 -9
  217. package/dist/types/privacy/shield-app.d.ts +1 -1
  218. package/dist/types/schema/effects.d.ts +132 -0
  219. package/dist/types/schema/fiber-app.d.ts +281 -0
  220. package/dist/types/schema/guards.d.ts +12 -0
  221. package/dist/types/templates/asset-policy.d.ts +119 -0
  222. package/dist/types/templates/index.d.ts +26 -0
  223. package/dist/types/templates/machine.d.ts +139 -0
  224. package/dist/types/templates/migration.d.ts +34 -0
  225. package/dist/types/templates/state-shape.d.ts +30 -0
  226. package/dist/types/zk/index.d.ts +4 -4
  227. package/package.json +31 -13
@@ -4,6 +4,121 @@
4
4
  * TypeScript-first definitions for fiber apps. This is the source of truth —
5
5
  * no JSON, no code generation. Import types directly.
6
6
  */
7
+ /**
8
+ * The wire (and authoring) tag for the `Immutable` policy VARIANT: the bare JSON string
9
+ * `"Immutable"`. EXACT casing, capital-I — this is the POLICY-LEVEL variant name and is
10
+ * DISTINCT from the `upgradePolicy` dial VALUE `"immutable"` (lowercase). The chain emits
11
+ * exactly this capital-I string for `Immutable`, so the SDK must too, byte-for-byte.
12
+ */
13
+ export const IMMUTABLE_POLICY = 'Immutable';
14
+ /** The names of the 15 policy dials, in declaration order. Used by the projector. */
15
+ const FIBER_POLICY_DIALS = [
16
+ 'selfReproducing',
17
+ 'allowedEffects',
18
+ 'spawnOwnerPolicy',
19
+ 'maxGenerations',
20
+ 'maxSpawnFanout',
21
+ 'acceptedCallers',
22
+ 'sealedStates',
23
+ 'transitionPolicy',
24
+ 'transferPolicy',
25
+ 'dependencyPolicy',
26
+ 'upgradePolicy',
27
+ 'version',
28
+ 'compatibleWith',
29
+ 'interfaces',
30
+ 'migrationAuthority',
31
+ ];
32
+ /**
33
+ * The canonical UNCONSTRAINED policy: omission. Provided as a named export for
34
+ * readability at call sites — `policy: unconstrained()` documents intent, and projects
35
+ * to NO `policy` key (identical to leaving `policy` off entirely).
36
+ */
37
+ export function unconstrained() {
38
+ return undefined;
39
+ }
40
+ /**
41
+ * The canonical IMMUTABLE policy: the definition is permanently locked. Projects to the
42
+ * bare JSON string `"Immutable"` ({@link IMMUTABLE_POLICY}), the chain's `Immutable`
43
+ * variant tag. Semantically equivalent to `constrained({ upgradePolicy: 'immutable' })`
44
+ * with no other dial set — which `constrained()`/`projectFiberPolicy()` collapse to the
45
+ * same string for wire parity (see {@link constrained}).
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * const def = defineFiberApp({ ...spec, policy: immutable() });
50
+ * ```
51
+ */
52
+ export function immutable() {
53
+ return IMMUTABLE_POLICY;
54
+ }
55
+ /**
56
+ * Build a CONSTRAINED `FiberPolicy` from any subset of the 15 dials.
57
+ *
58
+ * Pass only the dials you want to set. Dials left `undefined`/`null` are dropped so the
59
+ * result is a clean, minimal object that serializes identically to the chain's
60
+ * `dropNulls`-stripped `Constrained`. If NO dial is effectively set, this returns
61
+ * `undefined` (an empty constraint == `Unconstrained`), which projects to no `policy`
62
+ * key — preserving wire parity.
63
+ *
64
+ * CANONICAL COLLAPSE: `constrained({ upgradePolicy: 'immutable' })` with NO other dial set
65
+ * collapses to the bare string `"Immutable"` ({@link IMMUTABLE_POLICY}), because the chain
66
+ * collapses that exact `Constrained` into the `Immutable` variant. NOTE the casing: the
67
+ * collapse triggers on the chain's LOWERCASE upgradePolicy dial value `"immutable"`, and
68
+ * the result is the capital-I policy-variant tag `"Immutable"`. Signing the dials object
69
+ * `{ "upgradePolicy": "immutable" }` instead would diverge the canonical (the chain
70
+ * re-encodes it as `"Immutable"`) and break the create signature. Adding ANY other dial
71
+ * keeps it a dials object.
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * const policy = constrained({
76
+ * selfReproducing: false,
77
+ * maxGenerations: 3,
78
+ * allowedEffects: ['EMIT', 'TRANSFER'],
79
+ * sealedStates: ['ARCHIVED'],
80
+ * });
81
+ * ```
82
+ */
83
+ export function constrained(dials) {
84
+ const out = {};
85
+ for (const k of FIBER_POLICY_DIALS) {
86
+ const v = dials[k];
87
+ if (v === undefined || v === null)
88
+ continue;
89
+ out[k] = v;
90
+ }
91
+ const keys = Object.keys(out);
92
+ if (keys.length === 0)
93
+ return undefined;
94
+ // Canonical collapse: a lone LOWERCASE `upgradePolicy: 'immutable'` (the chain's dial
95
+ // value) IS the `Immutable` variant — emit the capital-I `"Immutable"` tag, not the dials.
96
+ if (keys.length === 1 && out.upgradePolicy === 'immutable')
97
+ return IMMUTABLE_POLICY;
98
+ return out;
99
+ }
100
+ /**
101
+ * Project an authoring `policy` value onto the wire form. Returns one of:
102
+ * - `undefined` when the policy is (effectively) `Unconstrained` — i.e. omit the `policy`
103
+ * key entirely;
104
+ * - the bare string `"Immutable"` ({@link IMMUTABLE_POLICY}) for the `Immutable` variant
105
+ * (also the collapse of a lone LOWERCASE `upgradePolicy: 'immutable'`); or
106
+ * - the minimal `Constrained` dials object otherwise.
107
+ *
108
+ * Centralizes the omit-on-unconstrained AND the Immutable-collapse parity rules so every
109
+ * projection path (`toProtoDefinition`, the genesis manifest) stays consistent.
110
+ */
111
+ export function projectFiberPolicy(policy) {
112
+ if (policy === undefined || policy === null)
113
+ return undefined;
114
+ // The Immutable variant is already its canonical bare-string wire form.
115
+ if (policy === IMMUTABLE_POLICY)
116
+ return IMMUTABLE_POLICY;
117
+ // Re-run the dial filter so a hand-built object with explicit-undefined/empty dials
118
+ // collapses to Unconstrained, and a lone `upgradePolicy: 'immutable'` collapses to
119
+ // `"Immutable"`, exactly like `constrained()` does.
120
+ return constrained(policy);
121
+ }
7
122
  // =============================================================================
8
123
  // Helper: defineFiberApp
9
124
  // =============================================================================
@@ -31,11 +146,11 @@ export function defineFiberApp(definition) {
31
146
  }
32
147
  /** Get valid transitions from a given state */
33
148
  export function getTransitionsFrom(def, state) {
34
- return def.transitions.filter(t => t.from === state);
149
+ return def.transitions.filter((t) => t.from === state);
35
150
  }
36
151
  /** Get valid event names from a given state */
37
152
  export function getEventsFrom(def, state) {
38
- return getTransitionsFrom(def, state).map(t => t.eventName);
153
+ return getTransitionsFrom(def, state).map((t) => t.eventName);
39
154
  }
40
155
  /** Check if a state is final */
41
156
  export function isFinalState(def, state) {
@@ -62,12 +177,17 @@ export function toProtoDefinition(def) {
62
177
  const protoDef = {
63
178
  states: {},
64
179
  initialState: def.initialState,
65
- transitions: def.transitions.map(t => ({
180
+ transitions: def.transitions.map((t) => ({
66
181
  from: t.from,
67
182
  to: t.to,
68
183
  eventName: t.eventName,
69
- guard: t.guard, // Required - Scala has no default
70
- effect: t.effect, // Required - Scala has no default
184
+ // guard/effect are REQUIRED by the Scala `Transition` case class (no defaults). The authoring
185
+ // `Transition` types them OPTIONAL for ergonomics, so ALWAYS project a concrete value here — an
186
+ // omitted key would serialize to `undefined`, get dropped, and fail the chain's decode (HTTP 400).
187
+ // The defaults are the exact shapes the chain's `PublishVersionSigningCanonicalSuite` accepts:
188
+ // an always-true guard `{"==":[1,1]}` and an empty (no-op) effect `{}`.
189
+ guard: t.guard ?? { '==': [1, 1] },
190
+ effect: t.effect ?? {},
71
191
  // Chain `Transition.dependencies: Set[UUID]` is REQUIRED (no Scala default), and each
72
192
  // element must be a fiber UUID string. A `DependencySpec` object is a build-time-only
73
193
  // authoring affordance with no wire representation (concrete dependency UUIDs are per
@@ -90,5 +210,14 @@ export function toProtoDefinition(def) {
90
210
  // change the signed digest of an otherwise-identical machine), so it is deliberately NOT emitted
91
211
  // (the chain's `StateMachineDefinition.metadata` stays absent → `None`). A caller that genuinely
92
212
  // needs on-chain metadata sets `ProtoStateMachineDefinition.metadata` explicitly after conversion.
213
+ // Fiber constitution. OMIT the `policy` key entirely for `Unconstrained` (the chain
214
+ // emits nothing for it); emit the bare string `"Immutable"` for `Immutable`; emit a bare
215
+ // object of only the SET dials for `Constrained`. `projectFiberPolicy` returns `undefined`
216
+ // for an (effectively) unconstrained policy, so we assign only when it is a real policy —
217
+ // keeping the wire byte-for-byte identical to the chain's encoding.
218
+ const policy = projectFiberPolicy(def.policy);
219
+ if (policy !== undefined) {
220
+ protoDef.policy = policy;
221
+ }
93
222
  return protoDef;
94
223
  }
@@ -58,11 +58,7 @@ export const LINT_CODES = {
58
58
  * The ONLY `$`-prefixed keys the engine injects (`ReservedKeys`). Anything else
59
59
  * (`$timestamp`, `$now`, ...) resolves to null on chain.
60
60
  */
61
- export const INJECTED_RESERVED_VARS = new Set([
62
- '$ordinal',
63
- '$lastSnapshotHash',
64
- '$epochProgress',
65
- ]);
61
+ export const INJECTED_RESERVED_VARS = new Set(['$ordinal', '$lastSnapshotHash', '$epochProgress']);
66
62
  /**
67
63
  * Tags that LOOK like opcodes and appear in real definitions but are NOT valid
68
64
  * JLVM operators — metakit mis-decodes each as a literal Map. These are always
@@ -117,11 +113,7 @@ export function lintGuardExpression(node, ctx, path, inDataLiteral = false) {
117
113
  const ref = obj.var;
118
114
  // The reference may be a string, or `[path, default]`, or (rarely) a
119
115
  // nested expression; only string refs carry the patterns we check.
120
- const refStr = typeof ref === 'string'
121
- ? ref
122
- : Array.isArray(ref) && typeof ref[0] === 'string'
123
- ? ref[0]
124
- : undefined;
116
+ const refStr = typeof ref === 'string' ? ref : Array.isArray(ref) && typeof ref[0] === 'string' ? ref[0] : undefined;
125
117
  if (refStr !== undefined) {
126
118
  // rule 1 — unknown reserved `$`-key
127
119
  if (refStr.startsWith('$') && !INJECTED_RESERVED_VARS.has(refStr)) {
@@ -150,8 +142,7 @@ export function lintGuardExpression(node, ctx, path, inDataLiteral = false) {
150
142
  });
151
143
  }
152
144
  // rule 3 — `witness.*` read inside a fiber transition
153
- if (ctx.flagWitness &&
154
- (refStr === 'witness' || refStr.startsWith('witness.'))) {
145
+ if (ctx.flagWitness && (refStr === 'witness' || refStr.startsWith('witness.'))) {
155
146
  out.push({
156
147
  app: ctx.app,
157
148
  transition: ctx.transition,
@@ -17,7 +17,7 @@
17
17
  * replacement for `{"===":[{"var":"event.agent"}, {"var":partyVar}]}`.
18
18
  */
19
19
  export const signerIsParty = (partyVar) => ({
20
- in: [{ var: partyVar }, { map: [{ var: "proofs" }, { var: "address" }] }],
20
+ in: [{ var: partyVar }, { map: [{ var: 'proofs' }, { var: 'address' }] }],
21
21
  });
22
22
  /** FIBER-transition authorization where ANY of the pinned parties signed (e.g. borrower OR lender). */
23
23
  export const signerIsAnyParty = (partyVars) => ({
@@ -29,17 +29,14 @@ export const signerIsAnyParty = (partyVars) => ({
29
29
  * The replay-safe replacement for `{"in":[{"var":"event.agent"}, {"var":setVar}]}`.
30
30
  */
31
31
  export const signerInSet = (setVar) => ({
32
- some: [
33
- { map: [{ var: "proofs" }, { var: "address" }] },
34
- { in: [{ var: "" }, { var: setVar }] },
35
- ],
32
+ some: [{ map: [{ var: 'proofs' }, { var: 'address' }] }, { in: [{ var: '' }, { var: setVar }] }],
36
33
  });
37
34
  /**
38
35
  * FIBER-transition ANTI-SELF guard: NO verified signer is the pinned party (e.g. a proposal author may
39
36
  * not vote on their own proposal). The replay-safe replacement for `{"!==":[{"var":"event.agent"}, {"var":partyVar}]}`.
40
37
  */
41
38
  export const signerIsNotParty = (partyVar) => ({
42
- "!": [signerIsParty(partyVar)],
39
+ '!': [signerIsParty(partyVar)],
43
40
  });
44
41
  /**
45
42
  * FIBER-transition authorization / dedup over a state MAP keyed by address: at least one VERIFIED signer
@@ -50,10 +47,7 @@ export const signerIsNotParty = (partyVar) => ({
50
47
  * `{"some":[{"map":[proofs,address]},{">=":[{"get":[mapVar,{"var":""}]}, N]}]}`.
51
48
  */
52
49
  export const signerHasEntry = (mapVar) => ({
53
- some: [
54
- { map: [{ var: "proofs" }, { var: "address" }] },
55
- { has: [{ var: mapVar }, { var: "" }] },
56
- ],
50
+ some: [{ map: [{ var: 'proofs' }, { var: 'address' }] }, { has: [{ var: mapVar }, { var: '' }] }],
57
51
  });
58
52
  /**
59
53
  * ASSET-op authorization (mintPolicy / burnPolicy / MorphismSpec.guard): the address at `addressVar`
@@ -61,7 +55,7 @@ export const signerHasEntry = (mapVar) => ({
61
55
  * `event` or `proofs` — it injects `signers` directly.
62
56
  */
63
57
  export const assetSignerIs = (addressVar) => ({
64
- in: [{ var: addressVar }, { var: "signers" }],
58
+ in: [{ var: addressVar }, { var: 'signers' }],
65
59
  });
66
60
  /**
67
61
  * EFFECT-KEY BINDING: prove the event's claimed actor (`actorVar`, default `event.agent`) is a
@@ -75,7 +69,7 @@ export const assetSignerIs = (addressVar) => ({
75
69
  * both signed and is authorized, and the effect can only write under that one verified key.
76
70
  * Structurally identical to {@link signerIsParty}; named for intent + greppability at write sites.
77
71
  */
78
- export const actorIsSigner = (actorVar = "event.agent") => signerIsParty(actorVar);
72
+ export const actorIsSigner = (actorVar = 'event.agent') => signerIsParty(actorVar);
79
73
  /**
80
74
  * EFFECT-KEY-BINDING membership: the event's claimed actor (`actorVar`, default `event.agent`) is BOTH
81
75
  * a CHAIN-VERIFIED signer AND a member of the pinned set `setVar` (e.g. `"state.signers"`,
@@ -86,7 +80,7 @@ export const actorIsSigner = (actorVar = "event.agent") => signerIsParty(actorVa
86
80
  * verified-but-unauthorized address as the key (padding a signature/vote tally). `actorInSet` pins both
87
81
  * to the same `actorVar`.
88
82
  */
89
- export const actorInSet = (setVar, actorVar = "event.agent") => ({
83
+ export const actorInSet = (setVar, actorVar = 'event.agent') => ({
90
84
  and: [actorIsSigner(actorVar), { in: [{ var: actorVar }, { var: setVar }] }],
91
85
  });
92
86
  /**
@@ -98,7 +92,7 @@ export const actorInSet = (setVar, actorVar = "event.agent") => ({
98
92
  * is an authorized member, closing the vote/signature-stuffing gap that bare {@link signerHasEntry}
99
93
  * leaves open (which only proves SOME verified signer is a key, not that the written key is).
100
94
  */
101
- export const actorHasEntry = (mapVar, actorVar = "event.agent") => ({
95
+ export const actorHasEntry = (mapVar, actorVar = 'event.agent') => ({
102
96
  and: [actorIsSigner(actorVar), { has: [{ var: mapVar }, { var: actorVar }] }],
103
97
  });
104
98
  /**
@@ -112,9 +106,9 @@ export const actorHasEntry = (mapVar, actorVar = "event.agent") => ({
112
106
  */
113
107
  export const signerHasReputation = (repMapVar, thresholdVar) => ({
114
108
  some: [
115
- { map: [{ var: "proofs" }, { var: "address" }] },
109
+ { map: [{ var: 'proofs' }, { var: 'address' }] },
116
110
  {
117
- ">=": [{ get: [{ var: repMapVar }, { var: "" }] }, { var: thresholdVar }],
111
+ '>=': [{ get: [{ var: repMapVar }, { var: '' }] }, { var: thresholdVar }],
118
112
  },
119
113
  ],
120
114
  });
@@ -139,26 +133,23 @@ export const signerHasRole = (roleMapVar) => signerHasEntry(roleMapVar);
139
133
  */
140
134
  export const signerHasReputationVia = (registryIdVar, thresholdVar) => ({
141
135
  if: [
142
- { has: [{ var: "machines" }, { var: registryIdVar }] },
136
+ { has: [{ var: 'machines' }, { var: registryIdVar }] },
143
137
  {
144
138
  some: [
145
- { map: [{ var: "proofs" }, { var: "address" }] },
139
+ { map: [{ var: 'proofs' }, { var: 'address' }] },
146
140
  {
147
- ">=": [
141
+ '>=': [
148
142
  {
149
143
  get: [
150
144
  {
151
145
  get: [
152
146
  {
153
- get: [
154
- { get: [{ var: "machines" }, { var: registryIdVar }] },
155
- "state",
156
- ],
147
+ get: [{ get: [{ var: 'machines' }, { var: registryIdVar }] }, 'state'],
157
148
  },
158
- "reputations",
149
+ 'reputations',
159
150
  ],
160
151
  },
161
- { var: "" },
152
+ { var: '' },
162
153
  ],
163
154
  },
164
155
  { var: thresholdVar },
@@ -179,24 +170,21 @@ export const signerHasReputationVia = (registryIdVar, thresholdVar) => ({
179
170
  */
180
171
  export const signerHasRoleVia = (registryIdVar, roleField) => ({
181
172
  if: [
182
- { has: [{ var: "machines" }, { var: registryIdVar }] },
173
+ { has: [{ var: 'machines' }, { var: registryIdVar }] },
183
174
  {
184
175
  some: [
185
- { map: [{ var: "proofs" }, { var: "address" }] },
176
+ { map: [{ var: 'proofs' }, { var: 'address' }] },
186
177
  {
187
178
  has: [
188
179
  {
189
180
  get: [
190
181
  {
191
- get: [
192
- { get: [{ var: "machines" }, { var: registryIdVar }] },
193
- "state",
194
- ],
182
+ get: [{ get: [{ var: 'machines' }, { var: registryIdVar }] }, 'state'],
195
183
  },
196
184
  roleField,
197
185
  ],
198
186
  },
199
- { var: "" },
187
+ { var: '' },
200
188
  ],
201
189
  },
202
190
  ],
@@ -215,14 +203,25 @@ export const signerHasRoleVia = (registryIdVar, roleField) => ({
215
203
  * so a single gated transition is split into a bind step then this assert step. See
216
204
  * docs/design/app-hardening-identity-integration.md §5–§6.
217
205
  */
206
+ /**
207
+ * EFFECT-KEY-BINDING dedup over an ARRAY of records: no existing element of the array at `arrayVar`
208
+ * (e.g. `"state.submissions"`, shaped `[ { addr, value }, … ]`) has its `field` (default `"addr"`)
209
+ * equal to the actor at `actorVar` (default `"event.agent"`). The array analog of the map-keyed
210
+ * `{"!":[has(...)]}` dedup — used where the collection is an append-only array of `{addr,…}` records
211
+ * (there is no `(array,string)` key check, but `none` over the array with a per-element `===` is total).
212
+ *
213
+ * The bare-element callback context inside `none` sees each record map directly, so `{get:[{var:""},field]}`
214
+ * is a valid `(map,string)` read. Pair with an `actorIsSigner`/`actorHasEntry` clause on the same
215
+ * `actorVar` (the dedup proves "not yet present", not "is the verified signer").
216
+ */
217
+ export const actorNotInArray = (arrayVar, field = 'addr', actorVar = 'event.agent') => ({
218
+ none: [{ var: arrayVar }, { '===': [{ get: [{ var: '' }, field] }, { var: actorVar }] }],
219
+ });
218
220
  export const depInState = (refVar, requiredState) => ({
219
221
  if: [
220
- { has: [{ var: "machines" }, { var: refVar }] },
222
+ { has: [{ var: 'machines' }, { var: refVar }] },
221
223
  {
222
- "==": [
223
- { get: [{ get: [{ var: "machines" }, { var: refVar }] }, "currentStateId"] },
224
- requiredState,
225
- ],
224
+ '==': [{ get: [{ get: [{ var: 'machines' }, { var: refVar }] }, 'currentStateId'] }, requiredState],
226
225
  },
227
226
  false,
228
227
  ],
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Asset-policy preset builders (§1.1 of the SDK std-lib/templates handoff).
3
+ *
4
+ * Each builder is a PURE function that emits the exact {@link CreateAssetPolicy} wire body the chain
5
+ * re-derives — no `Date.now()`/`Math.random()`/`crypto.randomUUID()`; fixed inputs → fixed output. The
6
+ * on-chain policy `schemaHash` and `logicHash` are both `RegistryShape.AssetPolicy.computeDigest` over
7
+ * `behavior`/`supply`/`morphisms`/`stateShape` (no JSON-Logic body), so these presets are pure data.
8
+ *
9
+ * Hard invariants (CLAUDE.md rule #1 — the signed canonical is frozen):
10
+ * - `behavior` is ALWAYS summed from {@link TOKEN_BEHAVIOR_BITS} (T=16, S=8, C=4, E=2, G=1), never a
11
+ * magic literal int.
12
+ * - `morphisms` is REQUIRED on the wire (presence required, emptiness meaningful) — emit `{}` when empty,
13
+ * NEVER omit it.
14
+ * - `supply` is REQUIRED — emit `{}` when there is no supply authority, never omit it.
15
+ * - Absent optionals are OMITTED, never emitted as `null`/`undefined` (the chain signs over
16
+ * `JCS(dropNulls(payload))`).
17
+ *
18
+ * @see src/ottochain/types.ts — CreateAssetPolicy, SupplyPolicy, MorphismSpec, MorphismKind, TOKEN_BEHAVIOR_BITS
19
+ */
20
+ import { TOKEN_BEHAVIOR_BITS, } from '../ottochain/types.js';
21
+ /** The default mint/burn guard the riverdale presets use: an always-true predicate `{"==":[1,1]}`. */
22
+ const alwaysTrue = () => ({ '==': [1, 1] });
23
+ /** A `PUBLIC`-visibility morphism spec (the riverdale preset visibility). Fresh object per call. */
24
+ const publicMorphism = () => ({ visibility: 'PUBLIC' });
25
+ /** Sum behavior bits from their NAMES — never a magic literal int (CLAUDE.md #1). */
26
+ export function sumBehavior(bits) {
27
+ return bits.reduce((acc, name) => acc + TOKEN_BEHAVIOR_BITS[name], 0);
28
+ }
29
+ /**
30
+ * Derive the default `stateShape.typeName`: strip a trailing `.asset` label, PascalCase the remainder
31
+ * (splitting on `.`/`-`/`_`/space), then append `State`.
32
+ * `rvd.asset` → `RvdState`, `goods.asset` → `GoodsState`, `capped.asset` → `CappedState`.
33
+ */
34
+ export function defaultStateTypeName(name) {
35
+ const ASSET_SUFFIX = '.asset';
36
+ const base = name.endsWith(ASSET_SUFFIX) ? name.slice(0, -ASSET_SUFFIX.length) : name;
37
+ const pascal = base
38
+ .split(/[.\-_\s]+/)
39
+ .filter(Boolean)
40
+ .map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1))
41
+ .join('');
42
+ return `${pascal}State`;
43
+ }
44
+ /** Build a {@link SupplyPolicy}, OMITTING every absent field (no `undefined`/`null` keys). */
45
+ function buildSupply(opts) {
46
+ const supply = {};
47
+ if (opts.maxSupply !== undefined)
48
+ supply.maxSupply = opts.maxSupply;
49
+ if (opts.mintPolicy !== undefined)
50
+ supply.mintPolicy = opts.mintPolicy;
51
+ if (opts.burnPolicy !== undefined)
52
+ supply.burnPolicy = opts.burnPolicy;
53
+ if (opts.decimals !== undefined)
54
+ supply.decimals = opts.decimals;
55
+ return supply;
56
+ }
57
+ /** Assemble the final {@link CreateAssetPolicy}, attaching `metadata` only when present. */
58
+ function assemble(args) {
59
+ const stateShape = {
60
+ typeName: args.stateTypeName ?? defaultStateTypeName(args.name),
61
+ fields: [],
62
+ };
63
+ const policy = {
64
+ name: args.name,
65
+ version: args.version,
66
+ behavior: args.behavior,
67
+ supply: args.supply,
68
+ morphisms: args.morphisms,
69
+ stateShape,
70
+ };
71
+ if (args.metadata !== undefined)
72
+ policy.metadata = args.metadata;
73
+ return policy;
74
+ }
75
+ /**
76
+ * Fungible currency. Behavior `T|S|C = 28` (transferable + splittable + combinable). Standard morphism
77
+ * set TRANSFER + FRACTIONALIZE + STAKE (`stakeable`, default true) + BURN (when `burnable`), all PUBLIC.
78
+ *
79
+ * Reproduces `riverdale-economy/rvd-policy.json` exactly via
80
+ * `fungiblePolicy({ name: 'rvd.asset', version: '1.0.0', mintable: true, burnable: true })`.
81
+ */
82
+ export function fungiblePolicy(p) {
83
+ const behavior = sumBehavior(['transferable', 'splittable', 'combinable']); // 28
84
+ const morphisms = {
85
+ TRANSFER: publicMorphism(),
86
+ FRACTIONALIZE: publicMorphism(),
87
+ };
88
+ if (p.stakeable !== false)
89
+ morphisms.STAKE = publicMorphism();
90
+ if (p.burnable)
91
+ morphisms.BURN = publicMorphism();
92
+ let mintPolicy;
93
+ if (p.mintGuard !== undefined)
94
+ mintPolicy = p.mintGuard;
95
+ else if (p.mintable)
96
+ mintPolicy = alwaysTrue();
97
+ const supply = buildSupply({
98
+ maxSupply: p.maxSupply,
99
+ mintPolicy,
100
+ burnPolicy: p.burnable ? alwaysTrue() : undefined,
101
+ decimals: p.decimals,
102
+ });
103
+ return assemble({
104
+ name: p.name,
105
+ version: p.version,
106
+ behavior,
107
+ supply,
108
+ morphisms,
109
+ stateTypeName: p.stateTypeName,
110
+ metadata: p.metadata,
111
+ });
112
+ }
113
+ /**
114
+ * Non-fungible token. Behavior `T = 16`, or `T|C = 20` with `combinable: true` (the riverdale
115
+ * `goods.asset`); `transferable: false` drops the T bit (a bound collectible). `morphisms` is `{}` by
116
+ * default (emitted explicitly, never omitted). Mintable by default ⇒ `supply.mintPolicy = {"==":[1,1]}`.
117
+ *
118
+ * Reproduces `riverdale-economy/goods-policy.json` exactly via
119
+ * `nftPolicy({ name: 'goods.asset', version: '1.0.0', combinable: true })`.
120
+ */
121
+ export function nftPolicy(p) {
122
+ const bits = [];
123
+ if (p.transferable !== false)
124
+ bits.push('transferable');
125
+ if (p.combinable)
126
+ bits.push('combinable');
127
+ const behavior = sumBehavior(bits);
128
+ let mintPolicy;
129
+ if (p.mintGuard !== undefined)
130
+ mintPolicy = p.mintGuard;
131
+ else if (p.mintable !== false)
132
+ mintPolicy = alwaysTrue();
133
+ const supply = buildSupply({ maxSupply: p.maxSupply, mintPolicy });
134
+ return assemble({
135
+ name: p.name,
136
+ version: p.version,
137
+ behavior,
138
+ supply,
139
+ morphisms: {},
140
+ stateTypeName: p.stateTypeName,
141
+ metadata: p.metadata,
142
+ });
143
+ }
144
+ /**
145
+ * Soulbound token: non-transferable, governable only (`G = 1`; `+E = 3` when `expirable`). No TRANSFER
146
+ * morphism (`morphisms: {}`); minting is closed after issue (empty `supply`).
147
+ */
148
+ export function soulboundPolicy(p) {
149
+ const bits = ['governable'];
150
+ if (p.expirable)
151
+ bits.push('expirable');
152
+ const behavior = sumBehavior(bits);
153
+ return assemble({
154
+ name: p.name,
155
+ version: p.version,
156
+ behavior,
157
+ supply: buildSupply({}), // mint closed after issue
158
+ morphisms: {}, // non-transferable: no TRANSFER morphism
159
+ stateTypeName: p.stateTypeName,
160
+ metadata: p.metadata,
161
+ });
162
+ }
163
+ /**
164
+ * Escape hatch: declare `behavior` by NAME (summed from {@link TOKEN_BEHAVIOR_BITS}, never a magic int)
165
+ * and pass `supply` + `morphisms` through raw. Use when no preset fits.
166
+ *
167
+ * Reproduces `riverdale-economy/capped-policy.json` exactly via
168
+ * `customPolicy({ name: 'capped.asset', version: '1.0.0',
169
+ * behavior: ['transferable', 'splittable', 'combinable'],
170
+ * supply: { maxSupply: 100, mintPolicy: { '==': [1, 1] } }, morphisms: {} })`.
171
+ */
172
+ export function customPolicy(p) {
173
+ return assemble({
174
+ name: p.name,
175
+ version: p.version,
176
+ behavior: sumBehavior(p.behavior),
177
+ supply: p.supply,
178
+ morphisms: p.morphisms,
179
+ stateTypeName: p.stateTypeName,
180
+ metadata: p.metadata,
181
+ });
182
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `@ottochain/sdk/templates` — the fiber & asset authoring template catalog.
3
+ *
4
+ * Typed builders that emit the EXACT canonical wire shapes app authors otherwise hand-roll as raw
5
+ * JSON-Logic (asset policies, versioned machines, effect directives, migrations, seeded state). Every
6
+ * builder is additive and pure — it returns the same wire shape the chain re-derives, so a template
7
+ * output signs to byte-identical `JCS(dropNulls(payload))` (CLAUDE.md rule #1). Hand-rolled JSON keeps
8
+ * working; these just make the recurring shapes typed, named, and mistake-resistant.
9
+ *
10
+ * Origin: the fiber-ergonomics program (ottochain `docs/proposals/fiber-ergonomics/`), Phase A — the
11
+ * `riverdale-economy` e2e is the migration proof (each preset reproduces its checked-in golden JSON).
12
+ *
13
+ * @example
14
+ * import {
15
+ * fungiblePolicy, machine, transition, effect, guard,
16
+ * transferAsset, triggers, spawn, seedState, seedFields,
17
+ * } from '@ottochain/sdk/templates';
18
+ */
19
+ // ─── 1.1 Asset-policy presets ────────────────────────────────────────────────
20
+ // fungiblePolicy / nftPolicy / soulboundPolicy / customPolicy (+ sumBehavior, defaultStateTypeName,
21
+ // BehaviorBitName) — emit a `CreateAssetPolicy`; behavior is summed from TOKEN_BEHAVIOR_BITS, never a literal.
22
+ export * from './asset-policy.js';
23
+ // ─── 1.2 Versioned-machine skeleton + transition()/effect() ──────────────────
24
+ // machine / transition / effect (+ TransitionSpec, MachineSpec, Machine, …). The skeleton owns ONE
25
+ // canonical wire definition, so publish + create cannot drift (verified binding, F9).
26
+ export * from './machine.js';
27
+ // ─── 1.4 Migration helpers ───────────────────────────────────────────────────
28
+ // seedFields / migration — hides the bare-state-root ({"var":""}) foot-gun.
29
+ export * from './migration.js';
30
+ // ─── 1.5 State-shape-with-defaults ───────────────────────────────────────────
31
+ // seedState / declaredFields / StateShape — auto-seed accumulators so no field reads null (F5).
32
+ export * from './state-shape.js';
33
+ // ─── 1.3 Effect-directive builders ───────────────────────────────────────────
34
+ // transferAsset / triggers / spawn / emit / toFiber / toWallet / addDependency / setDependencyActive /
35
+ // RESERVED_EFFECT_KEYS — a typo'd directive is a TS error, not a silent state field (F4).
36
+ export * from '../schema/effects.js';
37
+ // ─── Authorization-guard builders (namespace) ────────────────────────────────
38
+ // `guard.signerIsParty('state.borrower')` reads as intent at the call site.
39
+ export * as guard from '../schema/guards.js';
40
+ // ─── Existing machine/policy primitives re-surfaced for one-import authoring ──
41
+ export { defineFiberApp, toProtoDefinition, constrained, unconstrained, immutable, projectFiberPolicy, } from '../schema/fiber-app.js';