@ottochain/sdk 2.3.0 → 2.5.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/dist/cjs/apps/compute/index.js +33 -0
- package/dist/cjs/apps/compute/state-machines/compute-rule110.js +164 -0
- package/dist/cjs/apps/compute/state-machines/index.js +9 -0
- package/dist/cjs/apps/contracts/index.js +16 -9
- package/dist/cjs/apps/contracts/state-machines/contract-agreement.js +134 -161
- package/dist/cjs/apps/contracts/state-machines/contract-escrow.js +192 -170
- package/dist/cjs/apps/contracts/state-machines/contract-universal.js +46 -58
- package/dist/cjs/apps/corporate/index.js +2 -2
- package/dist/cjs/apps/corporate/state-machines/corp-board.js +500 -456
- package/dist/cjs/apps/corporate/state-machines/corp-entity.js +487 -361
- package/dist/cjs/apps/corporate/state-machines/corp-securities.js +769 -576
- package/dist/cjs/apps/corporate/state-machines/corp-shareholders.js +567 -557
- package/dist/cjs/apps/governance/index.js +21 -21
- package/dist/cjs/apps/governance/state-machines/dao-multisig.js +188 -209
- package/dist/cjs/apps/governance/state-machines/dao-reputation.js +181 -228
- package/dist/cjs/apps/governance/state-machines/dao-single.js +105 -88
- package/dist/cjs/apps/governance/state-machines/dao-token.js +199 -227
- package/dist/cjs/apps/governance/state-machines/governance-simple.js +231 -231
- package/dist/cjs/apps/governance/state-machines/governance-universal.js +64 -64
- package/dist/cjs/apps/identity/constants.js +55 -22
- package/dist/cjs/apps/identity/index.js +28 -12
- package/dist/cjs/apps/identity/state-machines/identity-agent.js +124 -158
- package/dist/cjs/apps/identity/state-machines/identity-oracle.js +158 -173
- package/dist/cjs/apps/identity/state-machines/identity-registry.js +262 -0
- package/dist/cjs/apps/identity/state-machines/identity-universal.js +51 -57
- package/dist/cjs/apps/identity/state-machines/index.js +3 -1
- package/dist/cjs/apps/index.js +22 -8
- package/dist/cjs/apps/lending/assets.js +247 -0
- package/dist/cjs/apps/lending/credit-scoring.js +87 -0
- package/dist/cjs/apps/lending/eligibility.js +105 -0
- package/dist/cjs/apps/lending/index.js +91 -0
- package/dist/cjs/apps/lending/state-machines/index.js +9 -0
- package/dist/cjs/apps/lending/state-machines/lending-zk-loan.js +433 -0
- package/dist/cjs/apps/markets/index.js +22 -12
- package/dist/cjs/apps/markets/state-machines/market-auction.js +116 -134
- package/dist/cjs/apps/markets/state-machines/market-crowdfund.js +131 -141
- package/dist/cjs/apps/markets/state-machines/market-group-buy.js +163 -184
- package/dist/cjs/apps/markets/state-machines/market-prediction.js +226 -233
- package/dist/cjs/apps/markets/state-machines/market-universal.js +65 -80
- package/dist/cjs/apps/oracles/index.js +3 -3
- package/dist/cjs/apps/privacy/index.js +67 -0
- package/dist/cjs/apps/privacy/state-machines/index.js +17 -0
- package/dist/cjs/apps/privacy/state-machines/mixer-ddhRing.js +286 -0
- package/dist/cjs/apps/privacy/state-machines/note-pool.js +476 -0
- package/dist/cjs/apps/staked-pool/assets.js +103 -0
- package/dist/cjs/apps/staked-pool/base.js +498 -0
- package/dist/cjs/apps/staked-pool/consumer.js +55 -0
- package/dist/cjs/apps/staked-pool/index.js +83 -0
- package/dist/cjs/apps/staked-pool/state-machines/index.js +12 -0
- package/dist/cjs/apps/staked-pool/state-machines/staked-pool-base.js +49 -0
- package/dist/cjs/apps/staked-pool/state-machines/staked-pool-oracle.js +131 -0
- package/dist/cjs/errors.js +3 -3
- package/dist/cjs/generated/google/protobuf/struct.js +5 -5
- package/dist/cjs/generated/google/protobuf/timestamp.js +1 -1
- package/dist/cjs/generated/index.js +11 -7
- package/dist/cjs/generated/openapi.js +6 -0
- package/dist/cjs/generated/ottochain/apps/contracts/v1/contract.js +51 -51
- package/dist/cjs/generated/ottochain/apps/corporate/v1/corporate.js +20 -21
- package/dist/cjs/generated/ottochain/apps/governance/v1/governance.js +14 -14
- package/dist/cjs/generated/ottochain/apps/identity/v1/attestation.js +5 -5
- package/dist/cjs/generated/ottochain/apps/identity/v1/identity.js +125 -131
- package/dist/cjs/generated/ottochain/apps/markets/v1/market.js +108 -108
- package/dist/cjs/generated/ottochain/v1/common.js +5 -5
- package/dist/cjs/generated/ottochain/v1/fiber.js +44 -6
- package/dist/cjs/generated/ottochain/v1/messages.js +1 -1
- package/dist/cjs/generated/ottochain/v1/records.js +1 -1
- package/dist/cjs/index.js +58 -7
- package/dist/cjs/openapi.js +2 -0
- package/dist/cjs/ottochain/drop-nulls.js +1 -2
- package/dist/cjs/ottochain/genesis-manifest.js +17 -11
- package/dist/cjs/ottochain/index.js +23 -13
- package/dist/cjs/ottochain/metagraph-client.js +81 -16
- package/dist/cjs/ottochain/snapshot.js +13 -16
- package/dist/cjs/ottochain/transaction.js +67 -14
- package/dist/cjs/ottochain/types.js +16 -2
- package/dist/cjs/privacy/index.js +14 -0
- package/dist/cjs/privacy/sealed-bid.js +213 -0
- package/dist/cjs/privacy/shield-app.js +131 -0
- package/dist/cjs/schema/effects.js +156 -0
- package/dist/cjs/schema/fiber-app.js +150 -15
- package/dist/cjs/schema/guard-lint.js +343 -0
- package/dist/cjs/schema/guards.js +246 -0
- package/dist/cjs/signing.js +80 -0
- package/dist/cjs/templates/asset-policy.js +190 -0
- package/dist/cjs/templates/index.js +86 -0
- package/dist/cjs/templates/machine.js +130 -0
- package/dist/cjs/templates/migration.js +39 -0
- package/dist/cjs/templates/state-shape.js +38 -0
- package/dist/cjs/types.js +2 -3
- package/dist/cjs/validation.js +9 -11
- package/dist/cjs/verify.js +9 -4
- package/dist/cjs/zk/commit.js +53 -0
- package/dist/cjs/zk/guard.js +107 -0
- package/dist/cjs/zk/index.js +48 -0
- package/dist/cjs/zk/preimage.js +37 -0
- package/dist/cjs/zk/prover.js +87 -0
- package/dist/cjs/zk/registry.js +62 -0
- package/dist/cjs/zk/types.js +28 -0
- package/dist/cjs/zk/witness.js +19 -0
- package/dist/esm/apps/compute/index.js +29 -0
- package/dist/esm/apps/compute/state-machines/compute-rule110.js +161 -0
- package/dist/esm/apps/compute/state-machines/index.js +5 -0
- package/dist/esm/apps/contracts/index.js +9 -5
- package/dist/esm/apps/contracts/state-machines/contract-agreement.js +135 -162
- package/dist/esm/apps/contracts/state-machines/contract-escrow.js +193 -171
- package/dist/esm/apps/contracts/state-machines/contract-universal.js +47 -59
- package/dist/esm/apps/corporate/index.js +2 -2
- package/dist/esm/apps/corporate/state-machines/corp-board.js +501 -457
- package/dist/esm/apps/corporate/state-machines/corp-entity.js +488 -362
- package/dist/esm/apps/corporate/state-machines/corp-securities.js +770 -577
- package/dist/esm/apps/corporate/state-machines/corp-shareholders.js +568 -558
- package/dist/esm/apps/governance/index.js +10 -10
- package/dist/esm/apps/governance/state-machines/dao-multisig.js +189 -210
- package/dist/esm/apps/governance/state-machines/dao-reputation.js +182 -229
- package/dist/esm/apps/governance/state-machines/dao-single.js +106 -89
- package/dist/esm/apps/governance/state-machines/dao-token.js +200 -228
- package/dist/esm/apps/governance/state-machines/governance-simple.js +232 -232
- package/dist/esm/apps/governance/state-machines/governance-universal.js +65 -65
- package/dist/esm/apps/identity/constants.js +52 -21
- package/dist/esm/apps/identity/index.js +14 -9
- package/dist/esm/apps/identity/state-machines/identity-agent.js +125 -159
- package/dist/esm/apps/identity/state-machines/identity-oracle.js +159 -174
- package/dist/esm/apps/identity/state-machines/identity-registry.js +259 -0
- package/dist/esm/apps/identity/state-machines/identity-universal.js +52 -58
- package/dist/esm/apps/identity/state-machines/index.js +1 -0
- package/dist/esm/apps/index.js +9 -5
- package/dist/esm/apps/lending/assets.js +231 -0
- package/dist/esm/apps/lending/credit-scoring.js +81 -0
- package/dist/esm/apps/lending/eligibility.js +99 -0
- package/dist/esm/apps/lending/index.js +69 -0
- package/dist/esm/apps/lending/state-machines/index.js +5 -0
- package/dist/esm/apps/lending/state-machines/lending-zk-loan.js +430 -0
- package/dist/esm/apps/markets/index.js +11 -7
- package/dist/esm/apps/markets/state-machines/market-auction.js +117 -135
- package/dist/esm/apps/markets/state-machines/market-crowdfund.js +132 -142
- package/dist/esm/apps/markets/state-machines/market-group-buy.js +164 -185
- package/dist/esm/apps/markets/state-machines/market-prediction.js +227 -234
- package/dist/esm/apps/markets/state-machines/market-universal.js +66 -81
- package/dist/esm/apps/oracles/index.js +3 -3
- package/dist/esm/apps/privacy/index.js +56 -0
- package/dist/esm/apps/privacy/state-machines/index.js +6 -0
- package/dist/esm/apps/privacy/state-machines/mixer-ddhRing.js +282 -0
- package/dist/esm/apps/privacy/state-machines/note-pool.js +470 -0
- package/dist/esm/apps/staked-pool/assets.js +91 -0
- package/dist/esm/apps/staked-pool/base.js +493 -0
- package/dist/esm/apps/staked-pool/consumer.js +49 -0
- package/dist/esm/apps/staked-pool/index.js +60 -0
- package/dist/esm/apps/staked-pool/state-machines/index.js +6 -0
- package/dist/esm/apps/staked-pool/state-machines/staked-pool-base.js +46 -0
- package/dist/esm/apps/staked-pool/state-machines/staked-pool-oracle.js +127 -0
- package/dist/esm/generated/google/protobuf/struct.js +1 -1
- package/dist/esm/generated/google/protobuf/timestamp.js +1 -1
- package/dist/esm/generated/index.js +9 -5
- package/dist/esm/generated/openapi.js +5 -0
- package/dist/esm/generated/ottochain/apps/contracts/v1/contract.js +47 -47
- package/dist/esm/generated/ottochain/apps/corporate/v1/corporate.js +1 -1
- package/dist/esm/generated/ottochain/apps/governance/v1/governance.js +1 -1
- package/dist/esm/generated/ottochain/apps/identity/v1/attestation.js +1 -1
- package/dist/esm/generated/ottochain/apps/identity/v1/identity.js +115 -121
- package/dist/esm/generated/ottochain/apps/markets/v1/market.js +101 -101
- package/dist/esm/generated/ottochain/v1/common.js +1 -1
- package/dist/esm/generated/ottochain/v1/fiber.js +40 -2
- package/dist/esm/generated/ottochain/v1/messages.js +1 -1
- package/dist/esm/generated/ottochain/v1/records.js +1 -1
- package/dist/esm/index.js +28 -3
- package/dist/esm/openapi.js +1 -0
- package/dist/esm/ottochain/genesis-manifest.js +15 -9
- package/dist/esm/ottochain/index.js +2 -3
- package/dist/esm/ottochain/metagraph-client.js +81 -16
- package/dist/esm/ottochain/snapshot.js +6 -8
- package/dist/esm/ottochain/transaction.js +51 -3
- package/dist/esm/ottochain/types.js +15 -1
- package/dist/esm/privacy/index.js +6 -0
- package/dist/esm/privacy/sealed-bid.js +209 -0
- package/dist/esm/privacy/shield-app.js +127 -0
- package/dist/esm/schema/effects.js +145 -0
- package/dist/esm/schema/fiber-app.js +139 -8
- package/dist/esm/schema/guard-lint.js +337 -0
- package/dist/esm/schema/guards.js +228 -0
- package/dist/esm/signing.js +74 -0
- package/dist/esm/templates/asset-policy.js +182 -0
- package/dist/esm/templates/index.js +41 -0
- package/dist/esm/templates/machine.js +125 -0
- package/dist/esm/templates/migration.js +34 -0
- package/dist/esm/templates/state-shape.js +34 -0
- package/dist/esm/validation.js +1 -3
- package/dist/esm/verify.js +8 -2
- package/dist/esm/zk/commit.js +44 -0
- package/dist/esm/zk/guard.js +99 -0
- package/dist/esm/zk/index.js +19 -0
- package/dist/esm/zk/preimage.js +30 -0
- package/dist/esm/zk/prover.js +82 -0
- package/dist/esm/zk/registry.js +55 -0
- package/dist/esm/zk/types.js +25 -0
- package/dist/esm/zk/witness.js +15 -0
- package/dist/types/apps/compute/index.d.ts +176 -0
- package/dist/types/apps/compute/state-machines/compute-rule110.d.ts +157 -0
- package/dist/types/apps/compute/state-machines/index.d.ts +5 -0
- package/dist/types/apps/contracts/index.d.ts +81 -221
- package/dist/types/apps/contracts/state-machines/contract-agreement.d.ts +23 -98
- package/dist/types/apps/contracts/state-machines/contract-escrow.d.ts +49 -115
- package/dist/types/apps/contracts/state-machines/contract-universal.d.ts +4 -4
- package/dist/types/apps/corporate/index.d.ts +1176 -440
- package/dist/types/apps/corporate/state-machines/corp-board.d.ts +271 -135
- package/dist/types/apps/corporate/state-machines/corp-entity.d.ts +279 -74
- package/dist/types/apps/corporate/state-machines/corp-securities.d.ts +373 -149
- package/dist/types/apps/corporate/state-machines/corp-shareholders.d.ts +252 -80
- package/dist/types/apps/governance/index.d.ts +368 -470
- package/dist/types/apps/governance/state-machines/dao-multisig.d.ts +92 -107
- package/dist/types/apps/governance/state-machines/dao-reputation.d.ts +61 -85
- package/dist/types/apps/governance/state-machines/dao-single.d.ts +25 -47
- package/dist/types/apps/governance/state-machines/dao-token.d.ts +79 -68
- package/dist/types/apps/governance/state-machines/governance-simple.d.ts +95 -125
- package/dist/types/apps/governance/state-machines/governance-universal.d.ts +6 -6
- package/dist/types/apps/identity/constants.d.ts +33 -5
- package/dist/types/apps/identity/index.d.ts +415 -131
- package/dist/types/apps/identity/state-machines/identity-agent.d.ts +23 -23
- package/dist/types/apps/identity/state-machines/identity-oracle.d.ts +27 -98
- package/dist/types/apps/identity/state-machines/identity-registry.d.ts +379 -0
- package/dist/types/apps/identity/state-machines/identity-universal.d.ts +4 -4
- package/dist/types/apps/identity/state-machines/index.d.ts +1 -0
- package/dist/types/apps/index.d.ts +9 -5
- package/dist/types/apps/lending/assets.d.ts +258 -0
- package/dist/types/apps/lending/credit-scoring.d.ts +80 -0
- package/dist/types/apps/lending/eligibility.d.ts +83 -0
- package/dist/types/apps/lending/index.d.ts +556 -0
- package/dist/types/apps/lending/state-machines/index.d.ts +5 -0
- package/dist/types/apps/lending/state-machines/lending-zk-loan.d.ts +536 -0
- package/dist/types/apps/markets/index.d.ts +181 -276
- package/dist/types/apps/markets/state-machines/market-auction.d.ts +25 -49
- package/dist/types/apps/markets/state-machines/market-crowdfund.d.ts +35 -53
- package/dist/types/apps/markets/state-machines/market-group-buy.d.ts +35 -61
- package/dist/types/apps/markets/state-machines/market-prediction.d.ts +65 -86
- package/dist/types/apps/markets/state-machines/market-universal.d.ts +12 -12
- package/dist/types/apps/oracles/index.d.ts +1 -1
- package/dist/types/apps/privacy/index.d.ts +328 -0
- package/dist/types/apps/privacy/state-machines/index.d.ts +6 -0
- package/dist/types/apps/privacy/state-machines/mixer-ddhRing.d.ts +337 -0
- package/dist/types/apps/privacy/state-machines/note-pool.d.ts +196 -0
- package/dist/types/apps/staked-pool/assets.d.ts +53 -0
- package/dist/types/apps/staked-pool/base.d.ts +80 -0
- package/dist/types/apps/staked-pool/consumer.d.ts +29 -0
- package/dist/types/apps/staked-pool/index.d.ts +51 -0
- package/dist/types/apps/staked-pool/state-machines/index.d.ts +6 -0
- package/dist/types/apps/staked-pool/state-machines/staked-pool-base.d.ts +8 -0
- package/dist/types/apps/staked-pool/state-machines/staked-pool-oracle.d.ts +34 -0
- package/dist/types/generated/index.d.ts +5 -5
- package/dist/types/generated/openapi.d.ts +1270 -0
- package/dist/types/generated/ottochain/apps/contracts/v1/contract.d.ts +5 -5
- package/dist/types/generated/ottochain/apps/identity/v1/identity.d.ts +12 -12
- package/dist/types/generated/ottochain/apps/markets/v1/market.d.ts +11 -11
- package/dist/types/generated/ottochain/v1/fiber.d.ts +7 -0
- package/dist/types/index.d.ts +7 -3
- package/dist/types/openapi.d.ts +24 -0
- package/dist/types/ottochain/genesis-manifest.d.ts +11 -5
- package/dist/types/ottochain/index.d.ts +5 -6
- package/dist/types/ottochain/metagraph-client.d.ts +49 -7
- package/dist/types/ottochain/snapshot.d.ts +6 -6
- package/dist/types/ottochain/transaction.d.ts +41 -1
- package/dist/types/ottochain/types.d.ts +336 -31
- package/dist/types/privacy/index.d.ts +6 -0
- package/dist/types/privacy/sealed-bid.d.ts +348 -0
- package/dist/types/privacy/shield-app.d.ts +48 -0
- package/dist/types/schema/effects.d.ts +141 -0
- package/dist/types/schema/fiber-app.d.ts +282 -2
- package/dist/types/schema/guard-lint.d.ts +111 -0
- package/dist/types/schema/guards.d.ts +146 -0
- package/dist/types/signing.d.ts +45 -0
- package/dist/types/templates/asset-policy.d.ts +119 -0
- package/dist/types/templates/index.d.ts +26 -0
- package/dist/types/templates/machine.d.ts +139 -0
- package/dist/types/templates/migration.d.ts +34 -0
- package/dist/types/templates/state-shape.d.ts +30 -0
- package/dist/types/validation.d.ts +22 -217
- package/dist/types/verify.d.ts +4 -0
- package/dist/types/zk/commit.d.ts +28 -0
- package/dist/types/zk/guard.d.ts +46 -0
- package/dist/types/zk/index.d.ts +19 -0
- package/dist/types/zk/preimage.d.ts +10 -0
- package/dist/types/zk/prover.d.ts +34 -0
- package/dist/types/zk/registry.d.ts +34 -0
- package/dist/types/zk/types.d.ts +33 -0
- package/dist/types/zk/witness.d.ts +40 -0
- package/package.json +47 -15
- package/dist/cjs/ottochain/normalize.js +0 -186
- package/dist/esm/ottochain/normalize.js +0 -179
- package/dist/types/ottochain/normalize.d.ts +0 -79
|
@@ -105,6 +105,269 @@ export interface Transition<TState extends string = string, TEvent extends strin
|
|
|
105
105
|
dependencies?: readonly (string | DependencySpec)[];
|
|
106
106
|
emits?: readonly (string | EmitSpec)[];
|
|
107
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* `allowedEffects` element — the 5 `EffectKind` families, UPPERCASE on the wire
|
|
110
|
+
* (`enumeratum` `Uppercase` mixin). Chain: `EffectKind` in `FiberPolicy.scala`.
|
|
111
|
+
*/
|
|
112
|
+
export type EffectKind = 'TRIGGER' | 'SPAWN' | 'EMIT' | 'TRANSFER' | 'DEPENDENCY';
|
|
113
|
+
/**
|
|
114
|
+
* `spawnOwnerPolicy` — UPPERCASE (`enumeratum` `Uppercase`). Chain: `SpawnOwnerPolicy`
|
|
115
|
+
* (`Explicit` / `SubsetOfParent` / `InheritParent` ⇒ `"EXPLICIT"` / `"SUBSETOFPARENT"`
|
|
116
|
+
* / `"INHERITPARENT"`).
|
|
117
|
+
*/
|
|
118
|
+
export type SpawnOwnerPolicy = 'EXPLICIT' | 'SUBSETOFPARENT' | 'INHERITPARENT';
|
|
119
|
+
/**
|
|
120
|
+
* `dependencyPolicy.mode` — UPPERCASE (`enumeratum` `Uppercase`). Chain: `DependencyMode`
|
|
121
|
+
* (`Open` / `Allowlist` / `Frozen`). REQUIRED on the wire (Scala defaults it to `Open`,
|
|
122
|
+
* but the `customizableEncoder` always encodes the value).
|
|
123
|
+
*/
|
|
124
|
+
export type DependencyMode = 'OPEN' | 'ALLOWLIST' | 'FROZEN';
|
|
125
|
+
/**
|
|
126
|
+
* `transferPolicy` — recipient allowlist for `_transferAsset`. Chain: `TransferPolicy`
|
|
127
|
+
* (`Option[Set[UUID]]` fibers, `Option[Set[Address]]` wallets). Each field is OPTIONAL;
|
|
128
|
+
* an absent field ⇒ that recipient class is unconstrained (and is `dropNulls`-stripped).
|
|
129
|
+
*/
|
|
130
|
+
export interface TransferPolicy {
|
|
131
|
+
/** Fiber UUIDs permitted to receive a transfer. */
|
|
132
|
+
allowedRecipientFibers?: readonly string[];
|
|
133
|
+
/** DAG wallet addresses permitted to receive a transfer. */
|
|
134
|
+
allowedRecipientWallets?: readonly string[];
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* `dependencyPolicy` — dynamic-dependency posture. Chain: `DependencyPolicy`
|
|
138
|
+
* (`mode: DependencyMode`, `allowed: Option[Set[UUID]]`). `mode` is REQUIRED; `allowed`
|
|
139
|
+
* is meaningful only when `mode === 'ALLOWLIST'` and is `dropNulls`-stripped otherwise.
|
|
140
|
+
*/
|
|
141
|
+
export interface DependencyPolicy {
|
|
142
|
+
/** Posture: `OPEN` (any target) / `ALLOWLIST` (only `allowed`) / `FROZEN` (no new). */
|
|
143
|
+
mode: DependencyMode;
|
|
144
|
+
/** Fiber UUIDs permitted as dependency targets (meaningful only under `ALLOWLIST`). */
|
|
145
|
+
allowed?: readonly string[];
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* `migrationAuthority` — who may authorize a `Governed` migration. Chain:
|
|
149
|
+
* `MigrationAuthority`, a DISJOINT-FIELD discriminated union (no tag key): the `Signers`
|
|
150
|
+
* arm carries `addresses`, the `Role` arm carries `registryFiberId` + `roleField`. The
|
|
151
|
+
* presence of disjoint fields is the discriminator (same as the chain decoder's `.or`).
|
|
152
|
+
*/
|
|
153
|
+
export type MigrationAuthority = {
|
|
154
|
+
/** VERIFIED signer DAG addresses permitted to authorize the migration (`Signers`). */
|
|
155
|
+
addresses: readonly string[];
|
|
156
|
+
} | {
|
|
157
|
+
/** Registry fiber UUID whose role-map is consulted (`Role`). */
|
|
158
|
+
registryFiberId: string;
|
|
159
|
+
/** Field/key in that fiber's state holding the `{<address>: true}` role map (`Role`). */
|
|
160
|
+
roleField: string;
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* `upgradePolicy` — the upgrade-path constitution. Chain: `UpgradePolicy`. The three
|
|
164
|
+
* bare variants encode as LOWERCASE tag STRINGS (`"immutable"` / `"appendOnly"` /
|
|
165
|
+
* `"arbitrary"`); the `Governed` arm encodes as the object `{ authority: <MigrationAuthority> }`.
|
|
166
|
+
*
|
|
167
|
+
* NOTE: this lowercase `"immutable"` is the upgradePolicy DIAL VALUE — distinct from the
|
|
168
|
+
* policy-level variant tag `"Immutable"` (capital-I), a different construct added in a
|
|
169
|
+
* later change.
|
|
170
|
+
*/
|
|
171
|
+
export type UpgradePolicy = 'immutable' | 'appendOnly' | 'arbitrary' | {
|
|
172
|
+
/** Authority that may consent to a `Governed` migration. */
|
|
173
|
+
authority: MigrationAuthority;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* `transitionPolicy` — WHO may drive a transition on this fiber. Chain: `TransitionPolicy`
|
|
177
|
+
* (chain PR #194), a bare tag STRING with three ranked levels:
|
|
178
|
+
*
|
|
179
|
+
* - `"Open"` — anyone may drive a transition; the transition's `guard` is the only gate.
|
|
180
|
+
* This is the chain DEFAULT when the dial is ABSENT, so omitting it is byte-identical
|
|
181
|
+
* to the legacy (pre-#194) behaviour.
|
|
182
|
+
* - `"OwnersOrParticipants"` — only the fiber's owners or its declared participants.
|
|
183
|
+
* - `"Owners"` — only the fiber's owners.
|
|
184
|
+
*
|
|
185
|
+
* Absent ⇒ `"Open"` (chain `transitionPolicy: Option[TransitionPolicy] = None`,
|
|
186
|
+
* `dropNulls`-stripped). The chain joins this to the tighten-only upgrade lattice, so an
|
|
187
|
+
* upgrade may only RAISE the level (`Open < OwnersOrParticipants < Owners`); LOOSENING it
|
|
188
|
+
* (including dropping the dial on a fiber that had it set) is rejected as `CombineRejected`.
|
|
189
|
+
*/
|
|
190
|
+
export type TransitionPolicy = 'Open' | 'OwnersOrParticipants' | 'Owners';
|
|
191
|
+
/**
|
|
192
|
+
* `compatibleWith` — the inclusive-min / exclusive-max SemVer bridge window a migration
|
|
193
|
+
* may target. Chain: `VersionRange` (`min: Option[SemVer]`, `max: Option[SemVer]`). Each
|
|
194
|
+
* bound is a SemVer STRING (`"1.2.3"`); an absent bound is unconstrained on that side and
|
|
195
|
+
* is `dropNulls`-stripped.
|
|
196
|
+
*/
|
|
197
|
+
export interface VersionRange {
|
|
198
|
+
/** Inclusive lower bound, e.g. `"1.0.0"` (absent ⇒ unconstrained below). */
|
|
199
|
+
min?: string;
|
|
200
|
+
/** Exclusive upper bound, e.g. `"2.0.0"` (absent ⇒ unconstrained above). */
|
|
201
|
+
max?: string;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* `FiberPolicy` — the constitution a definition declares for the fibers it spawns.
|
|
205
|
+
*
|
|
206
|
+
* This MIRRORS the chain ADT `FiberPolicy = Unconstrained | Immutable | Constrained(<dials>)`
|
|
207
|
+
* (chain branch `feat/fiber-policy-adt`). The representation here is chosen for
|
|
208
|
+
* BYTE-FOR-BYTE wire parity with the chain, because a `StateMachineDefinition` is
|
|
209
|
+
* signed verbatim by the SDK (`batchSign(dropNulls(...))`) and re-encoded + verified
|
|
210
|
+
* by the chain. The rule is:
|
|
211
|
+
*
|
|
212
|
+
* - **`Unconstrained`** ⇒ there is **NO `policy` key** on the wire definition at all.
|
|
213
|
+
* In the SDK this is the DEFAULT and is represented by simply OMITTING `policy`
|
|
214
|
+
* (i.e. `policy === undefined`).
|
|
215
|
+
* - **`Immutable`** ⇒ the definition is permanently locked; `policy` is the bare JSON
|
|
216
|
+
* STRING `"Immutable"` (EXACT casing, capital-I) — NOT an object. Semantically this is
|
|
217
|
+
* the upgradePolicy DIAL set to its LOWERCASE `"immutable"` value with no other dial
|
|
218
|
+
* set, and the chain collapses that exact `Constrained` into the `Immutable` variant.
|
|
219
|
+
* See {@link immutable} and the canonical collapse in {@link projectFiberPolicy}.
|
|
220
|
+
* - **`Constrained(dials)`** ⇒ `policy` is a bare object of ONLY the dials that are
|
|
221
|
+
* SET. Unset dials are absent (the chain `dropNulls`-strips them; so does the SDK
|
|
222
|
+
* at sign time). A `Constrained` with no dials set is wire-indistinguishable from
|
|
223
|
+
* `Unconstrained`, so `toProtoDefinition` collapses it back to "no policy key".
|
|
224
|
+
*
|
|
225
|
+
* All 15 dials are optional. Provide any subset.
|
|
226
|
+
*/
|
|
227
|
+
export interface FiberPolicyDials {
|
|
228
|
+
/** Whether the fiber may reproduce itself (spawn instances of its own definition). Wire: boolean. */
|
|
229
|
+
selfReproducing?: boolean;
|
|
230
|
+
/**
|
|
231
|
+
* Allow-list of effect families this fiber's transitions may produce, as a SET of the 5
|
|
232
|
+
* UPPERCASE {@link EffectKind} tokens (`"TRIGGER" | "SPAWN" | "EMIT" | "TRANSFER" |
|
|
233
|
+
* "DEPENDENCY"`). Order is not significant; duplicates are collapsed by the chain's `Set`.
|
|
234
|
+
* Chain: `allowedEffects: Option[Set[EffectKind]]`.
|
|
235
|
+
*/
|
|
236
|
+
allowedEffects?: readonly EffectKind[];
|
|
237
|
+
/**
|
|
238
|
+
* Who/what may own fibers this one spawns — an UPPERCASE {@link SpawnOwnerPolicy} token
|
|
239
|
+
* (`"EXPLICIT" | "SUBSETOFPARENT" | "INHERITPARENT"`). Chain: `spawnOwnerPolicy: Option[SpawnOwnerPolicy]`.
|
|
240
|
+
*/
|
|
241
|
+
spawnOwnerPolicy?: SpawnOwnerPolicy;
|
|
242
|
+
/** Maximum spawn-generation depth (descendant chain length). Wire: number. */
|
|
243
|
+
maxGenerations?: number;
|
|
244
|
+
/** Maximum number of children a single transition may spawn. Wire: number. */
|
|
245
|
+
maxSpawnFanout?: number;
|
|
246
|
+
/** SET of caller fiber UUIDs permitted to drive transitions on this fiber. Wire: string[]. */
|
|
247
|
+
acceptedCallers?: readonly string[];
|
|
248
|
+
/** SET of state ids that are sealed (no transition may fire from them). Wire: string[]. */
|
|
249
|
+
sealedStates?: readonly string[];
|
|
250
|
+
/**
|
|
251
|
+
* WHO may drive a transition on this fiber — a {@link TransitionPolicy} bare tag
|
|
252
|
+
* (`"Open" | "OwnersOrParticipants" | "Owners"`). Absent ⇒ `"Open"` (guard-only, the
|
|
253
|
+
* chain default); set `"Owners"`/`"OwnersOrParticipants"` to gate transitions by identity
|
|
254
|
+
* in ADDITION to the guard. Chain: `transitionPolicy: Option[TransitionPolicy]` (chain PR #194).
|
|
255
|
+
*/
|
|
256
|
+
transitionPolicy?: TransitionPolicy;
|
|
257
|
+
/**
|
|
258
|
+
* Recipient allowlist for `_transferAsset` — the {@link TransferPolicy} object
|
|
259
|
+
* `{ allowedRecipientFibers?: uuid[], allowedRecipientWallets?: DAG-address[] }`.
|
|
260
|
+
* Chain: `transferPolicy: Option[TransferPolicy]`.
|
|
261
|
+
*/
|
|
262
|
+
transferPolicy?: TransferPolicy;
|
|
263
|
+
/**
|
|
264
|
+
* Dynamic-dependency policy — the {@link DependencyPolicy} object `{ mode, allowed? }`
|
|
265
|
+
* where `mode` is the REQUIRED UPPERCASE {@link DependencyMode}. Chain:
|
|
266
|
+
* `dependencyPolicy: Option[DependencyPolicy]`.
|
|
267
|
+
*/
|
|
268
|
+
dependencyPolicy?: DependencyPolicy;
|
|
269
|
+
/**
|
|
270
|
+
* In-place upgrade/migration posture — an {@link UpgradePolicy}: a LOWERCASE bare tag
|
|
271
|
+
* (`"immutable" | "appendOnly" | "arbitrary"`) OR the `Governed` object
|
|
272
|
+
* `{ authority: <MigrationAuthority> }`. Chain: `upgradePolicy: Option[UpgradePolicy]`.
|
|
273
|
+
*/
|
|
274
|
+
upgradePolicy?: UpgradePolicy;
|
|
275
|
+
/** Self-declared SemVer of this definition as a STRING `"major.minor.patch"` (e.g. `"1.2.3"`). Chain: `version: Option[SemVer]`. */
|
|
276
|
+
version?: string;
|
|
277
|
+
/**
|
|
278
|
+
* Migration bridge window — the {@link VersionRange} object `{ min?: semver, max?: semver }`
|
|
279
|
+
* naming the successor versions this definition declares it will migrate TO. Chain:
|
|
280
|
+
* `compatibleWith: Option[VersionRange]`.
|
|
281
|
+
*/
|
|
282
|
+
compatibleWith?: VersionRange;
|
|
283
|
+
/** SET of (ERC-165-style) interface identifiers this definition advertises. Wire: string[]. */
|
|
284
|
+
interfaces?: readonly string[];
|
|
285
|
+
/**
|
|
286
|
+
* Authority permitted to authorize a `Governed` migration — a {@link MigrationAuthority}:
|
|
287
|
+
* `{ addresses: DAG-address[] }` (Signers) OR `{ registryFiberId: uuid, roleField: string }`
|
|
288
|
+
* (Role), discriminated by disjoint fields. Chain: `migrationAuthority: Option[MigrationAuthority]`.
|
|
289
|
+
*/
|
|
290
|
+
migrationAuthority?: MigrationAuthority;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* The wire (and authoring) tag for the `Immutable` policy VARIANT: the bare JSON string
|
|
294
|
+
* `"Immutable"`. EXACT casing, capital-I — this is the POLICY-LEVEL variant name and is
|
|
295
|
+
* DISTINCT from the `upgradePolicy` dial VALUE `"immutable"` (lowercase). The chain emits
|
|
296
|
+
* exactly this capital-I string for `Immutable`, so the SDK must too, byte-for-byte.
|
|
297
|
+
*/
|
|
298
|
+
export declare const IMMUTABLE_POLICY: "Immutable";
|
|
299
|
+
export type ImmutablePolicy = typeof IMMUTABLE_POLICY;
|
|
300
|
+
/**
|
|
301
|
+
* Wire form of a `FiberPolicy`. Mirrors the chain ADT's non-`Unconstrained` arms:
|
|
302
|
+
*
|
|
303
|
+
* - a bare object of the SET dials — the `Constrained` arm. Unset dials are stripped at
|
|
304
|
+
* projection time (and again by `dropNulls` at sign time), so this object matches the
|
|
305
|
+
* chain's `dropNulls`-stripped `Constrained` encoding exactly; OR
|
|
306
|
+
* - the bare JSON string `"Immutable"` — the {@link ImmutablePolicy} arm.
|
|
307
|
+
*
|
|
308
|
+
* (`Unconstrained` has no wire representation: it is the absence of the `policy` key.)
|
|
309
|
+
*/
|
|
310
|
+
export type FiberPolicy = FiberPolicyDials | ImmutablePolicy;
|
|
311
|
+
/**
|
|
312
|
+
* The canonical UNCONSTRAINED policy: omission. Provided as a named export for
|
|
313
|
+
* readability at call sites — `policy: unconstrained()` documents intent, and projects
|
|
314
|
+
* to NO `policy` key (identical to leaving `policy` off entirely).
|
|
315
|
+
*/
|
|
316
|
+
export declare function unconstrained(): undefined;
|
|
317
|
+
/**
|
|
318
|
+
* The canonical IMMUTABLE policy: the definition is permanently locked. Projects to the
|
|
319
|
+
* bare JSON string `"Immutable"` ({@link IMMUTABLE_POLICY}), the chain's `Immutable`
|
|
320
|
+
* variant tag. Semantically equivalent to `constrained({ upgradePolicy: 'immutable' })`
|
|
321
|
+
* with no other dial set — which `constrained()`/`projectFiberPolicy()` collapse to the
|
|
322
|
+
* same string for wire parity (see {@link constrained}).
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```ts
|
|
326
|
+
* const def = defineFiberApp({ ...spec, policy: immutable() });
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
export declare function immutable(): ImmutablePolicy;
|
|
330
|
+
/**
|
|
331
|
+
* Build a CONSTRAINED `FiberPolicy` from any subset of the 15 dials.
|
|
332
|
+
*
|
|
333
|
+
* Pass only the dials you want to set. Dials left `undefined`/`null` are dropped so the
|
|
334
|
+
* result is a clean, minimal object that serializes identically to the chain's
|
|
335
|
+
* `dropNulls`-stripped `Constrained`. If NO dial is effectively set, this returns
|
|
336
|
+
* `undefined` (an empty constraint == `Unconstrained`), which projects to no `policy`
|
|
337
|
+
* key — preserving wire parity.
|
|
338
|
+
*
|
|
339
|
+
* CANONICAL COLLAPSE: `constrained({ upgradePolicy: 'immutable' })` with NO other dial set
|
|
340
|
+
* collapses to the bare string `"Immutable"` ({@link IMMUTABLE_POLICY}), because the chain
|
|
341
|
+
* collapses that exact `Constrained` into the `Immutable` variant. NOTE the casing: the
|
|
342
|
+
* collapse triggers on the chain's LOWERCASE upgradePolicy dial value `"immutable"`, and
|
|
343
|
+
* the result is the capital-I policy-variant tag `"Immutable"`. Signing the dials object
|
|
344
|
+
* `{ "upgradePolicy": "immutable" }` instead would diverge the canonical (the chain
|
|
345
|
+
* re-encodes it as `"Immutable"`) and break the create signature. Adding ANY other dial
|
|
346
|
+
* keeps it a dials object.
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* ```ts
|
|
350
|
+
* const policy = constrained({
|
|
351
|
+
* selfReproducing: false,
|
|
352
|
+
* maxGenerations: 3,
|
|
353
|
+
* allowedEffects: ['EMIT', 'TRANSFER'],
|
|
354
|
+
* sealedStates: ['ARCHIVED'],
|
|
355
|
+
* });
|
|
356
|
+
* ```
|
|
357
|
+
*/
|
|
358
|
+
export declare function constrained(dials: FiberPolicyDials): FiberPolicy | undefined;
|
|
359
|
+
/**
|
|
360
|
+
* Project an authoring `policy` value onto the wire form. Returns one of:
|
|
361
|
+
* - `undefined` when the policy is (effectively) `Unconstrained` — i.e. omit the `policy`
|
|
362
|
+
* key entirely;
|
|
363
|
+
* - the bare string `"Immutable"` ({@link IMMUTABLE_POLICY}) for the `Immutable` variant
|
|
364
|
+
* (also the collapse of a lone LOWERCASE `upgradePolicy: 'immutable'`); or
|
|
365
|
+
* - the minimal `Constrained` dials object otherwise.
|
|
366
|
+
*
|
|
367
|
+
* Centralizes the omit-on-unconstrained AND the Immutable-collapse parity rules so every
|
|
368
|
+
* projection path (`toProtoDefinition`, the genesis manifest) stays consistent.
|
|
369
|
+
*/
|
|
370
|
+
export declare function projectFiberPolicy(policy: FiberPolicy | undefined): FiberPolicy | undefined;
|
|
108
371
|
export interface FiberAppMetadata {
|
|
109
372
|
name: string;
|
|
110
373
|
app: string;
|
|
@@ -125,6 +388,16 @@ export interface CrossReferences {
|
|
|
125
388
|
}
|
|
126
389
|
export interface FiberAppDefinition<TState extends string = string, TEvent extends string = string> {
|
|
127
390
|
metadata: FiberAppMetadata;
|
|
391
|
+
/**
|
|
392
|
+
* Fiber constitution. Mirrors the chain ADT `FiberPolicy = Unconstrained | Immutable |
|
|
393
|
+
* Constrained(<dials>)`. OMIT this field (the default) for `Unconstrained` — the projected
|
|
394
|
+
* wire definition then has NO `policy` key. Set it to `immutable()` to permanently lock the
|
|
395
|
+
* definition (projects to the bare string `"Immutable"`). Set it to a `constrained({...})`
|
|
396
|
+
* object to declare a subset of the 15 dials; unset dials are stripped so the wire form
|
|
397
|
+
* matches the chain's `dropNulls`-stripped `Constrained` byte-for-byte (and a lone
|
|
398
|
+
* `upgradePolicy: 'immutable'` collapses to `"Immutable"`).
|
|
399
|
+
*/
|
|
400
|
+
policy?: FiberPolicy;
|
|
128
401
|
/** Schema for fiber creation inputs (user-provided) */
|
|
129
402
|
createSchema?: {
|
|
130
403
|
required?: readonly string[];
|
|
@@ -192,10 +465,17 @@ export interface ProtoStateMachineDefinition {
|
|
|
192
465
|
eventName: string;
|
|
193
466
|
guard?: unknown;
|
|
194
467
|
effect?: unknown;
|
|
195
|
-
dependencies
|
|
196
|
-
emits?: unknown[];
|
|
468
|
+
dependencies: string[];
|
|
197
469
|
}>;
|
|
198
470
|
metadata?: Record<string, unknown>;
|
|
471
|
+
/**
|
|
472
|
+
* Fiber constitution. PRESENT for `Constrained` (a bare object of the SET dials) and for
|
|
473
|
+
* `Immutable` (the bare string `"Immutable"`); ABSENT for `Unconstrained`. This
|
|
474
|
+
* omit-on-unconstrained rule is the wire parity contract: the chain emits no `policy` key
|
|
475
|
+
* for `Unconstrained`, so neither may the SDK, or the signature breaks (HTTP 400). See
|
|
476
|
+
* {@link projectFiberPolicy}.
|
|
477
|
+
*/
|
|
478
|
+
policy?: FiberPolicy;
|
|
199
479
|
}
|
|
200
480
|
/**
|
|
201
481
|
* Extract proto-compatible StateMachineDefinition from a FiberAppDefinition.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression-prevention lint for OttoChain std-app fiber definitions.
|
|
3
|
+
*
|
|
4
|
+
* Purpose
|
|
5
|
+
* -------
|
|
6
|
+
* Catch — at *authoring* time — the classes of SDK↔chain drift that the chain
|
|
7
|
+
* accepts structurally but then silently mis-parses, drops, or evaluates to a
|
|
8
|
+
* dead (always-true / always-false / always-throw) guard. Without this lint
|
|
9
|
+
* those mistakes ship as live, exploitable holes or as silent data corruption
|
|
10
|
+
* because nothing in `defineFiberApp` / `toProtoDefinition` rejects them.
|
|
11
|
+
*
|
|
12
|
+
* The drift classes (cross-referenced to docs/reviews/fiber-app-alignment-audit-2026-06.md):
|
|
13
|
+
*
|
|
14
|
+
* A1 — `$timestamp` (and any non-injected `$`-key). `ReservedKeys` injects ONLY
|
|
15
|
+
* `$ordinal`, `$lastSnapshotHash`, `$epochProgress`. `{"var":"$timestamp"}`
|
|
16
|
+
* resolves to null → `0` in numeric contexts → deadline guards die silently.
|
|
17
|
+
*
|
|
18
|
+
* A2 — Nonexistent JLVM opcodes used as operator tags: `size`, `getKey`,
|
|
19
|
+
* `setKey`, `deleteKey`. metakit decodes an unknown single-key object as a
|
|
20
|
+
* LITERAL Map, not an operator, so the guard is always-true/false and the
|
|
21
|
+
* effect writes a junk key. (Canonical good set: `KNOWN_OPERATORS`.)
|
|
22
|
+
*
|
|
23
|
+
* A3 — SDK directives the chain's `toProtoDefinition` silently drops:
|
|
24
|
+
* transition-level `emits` / `spawns`, and object-form `dependencies`
|
|
25
|
+
* entries `{machine,instanceRef,requiredState}` (chain parses `Set[UUID]`).
|
|
26
|
+
* Authors believe these gate/emit; on-chain they evaporate.
|
|
27
|
+
*
|
|
28
|
+
* per-context — `{"var":"witness.*"}` in a fiber TRANSITION. `witness` is only
|
|
29
|
+
* injected in ASSET-guard contexts; a transition gets `event` (the proof
|
|
30
|
+
* rides under `event.witness.*`). Reading `witness.*` resolves to null →
|
|
31
|
+
* fail-closed (zk gate un-passable) or silently bypassed.
|
|
32
|
+
*
|
|
33
|
+
* leading-dot — `{"var":".foo"}` resolves to null on chain.
|
|
34
|
+
*
|
|
35
|
+
* This is a STANDALONE validator. It is deliberately NOT wired into
|
|
36
|
+
* `defineFiberApp` / `toProtoDefinition`: doing so would break the build until
|
|
37
|
+
* every app is remediated. Run it via `scripts/lint-apps.mjs`.
|
|
38
|
+
*/
|
|
39
|
+
import type { FiberAppDefinition } from './fiber-app.js';
|
|
40
|
+
export type LintSeverity = 'error' | 'warn';
|
|
41
|
+
export interface LintViolation {
|
|
42
|
+
/** App identifier (`metadata.app/metadata.type` or `metadata.name`), when known. */
|
|
43
|
+
app?: string;
|
|
44
|
+
/** `eventName` (or `from→to`) of the offending transition, when applicable. */
|
|
45
|
+
transition?: string;
|
|
46
|
+
severity: LintSeverity;
|
|
47
|
+
/** Stable machine-readable rule code (see {@link LINT_CODES}). */
|
|
48
|
+
code: string;
|
|
49
|
+
/** Human-readable explanation including the correct alternative. */
|
|
50
|
+
message: string;
|
|
51
|
+
/** JSON-ish path to the offending node, e.g. `transitions[3].guard.or[0].var`. */
|
|
52
|
+
path: string;
|
|
53
|
+
}
|
|
54
|
+
/** Stable rule codes — referenced by tests and by report tooling. */
|
|
55
|
+
export declare const LINT_CODES: {
|
|
56
|
+
readonly UNKNOWN_RESERVED_VAR: "unknown-reserved-var";
|
|
57
|
+
readonly UNKNOWN_OPERATOR: "unknown-operator";
|
|
58
|
+
readonly WITNESS_IN_TRANSITION: "witness-in-transition";
|
|
59
|
+
readonly DROPPED_DIRECTIVE: "dropped-directive";
|
|
60
|
+
readonly LEADING_DOT_VAR: "leading-dot-var";
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* The ONLY `$`-prefixed keys the engine injects (`ReservedKeys`). Anything else
|
|
64
|
+
* (`$timestamp`, `$now`, ...) resolves to null on chain.
|
|
65
|
+
*/
|
|
66
|
+
export declare const INJECTED_RESERVED_VARS: ReadonlySet<string>;
|
|
67
|
+
/**
|
|
68
|
+
* Tags that LOOK like opcodes and appear in real definitions but are NOT valid
|
|
69
|
+
* JLVM operators — metakit mis-decodes each as a literal Map. These are always
|
|
70
|
+
* flagged as errors regardless of position (they are not plausible data fields).
|
|
71
|
+
* Mapped to the correct replacement opcode for the message.
|
|
72
|
+
*/
|
|
73
|
+
export declare const KNOWN_BAD_OPERATORS: ReadonlyMap<string, string>;
|
|
74
|
+
interface WalkContext {
|
|
75
|
+
app?: string;
|
|
76
|
+
transition?: string;
|
|
77
|
+
/**
|
|
78
|
+
* When true, this transition expression runs in a context where `witness` is
|
|
79
|
+
* NOT injected (a fiber transition guard/effect). Reading `witness.*` here is
|
|
80
|
+
* a bug (rule 3). Asset-guard contexts would set this false (not walked here).
|
|
81
|
+
*/
|
|
82
|
+
flagWitness: boolean;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Recursively lint a single JSON-Logic expression (a guard or an effect, or any
|
|
86
|
+
* sub-node). Walks every nested operand. Pushes a {@link LintViolation} for each
|
|
87
|
+
* rule-1 / rule-2 / rule-3 / rule-5 hit found at or below `node`.
|
|
88
|
+
*
|
|
89
|
+
* `inDataLiteral` tracks whether `node` sits in a position the evaluator treats
|
|
90
|
+
* as DATA rather than as an expression to evaluate (e.g. the 2nd operand of
|
|
91
|
+
* `merge`/`cat`, or a value nested inside such an operand). In a data-literal
|
|
92
|
+
* position an unknown single-key object is a legitimate field map, so the
|
|
93
|
+
* *generic* unknown-operator warning is suppressed there — but `$`-var keys,
|
|
94
|
+
* leading-dot vars, witness reads, and the known-BAD opcode tags are still
|
|
95
|
+
* flagged (those are bugs wherever they appear).
|
|
96
|
+
*/
|
|
97
|
+
export declare function lintGuardExpression(node: unknown, ctx: WalkContext, path: string, inDataLiteral?: boolean): LintViolation[];
|
|
98
|
+
/**
|
|
99
|
+
* Lint a complete fiber app definition. Walks every transition guard + effect
|
|
100
|
+
* (rules 1/2/3/5) and every transition's structural directives (rule 4), plus a
|
|
101
|
+
* light pass over `states` to catch stray reserved-key / operator drift embedded
|
|
102
|
+
* in state metadata. Returns ALL violations (errors and warnings); callers
|
|
103
|
+
* decide the exit policy (e.g. fail on any `error`).
|
|
104
|
+
*/
|
|
105
|
+
export declare function lintFiberApp(def: FiberAppDefinition): LintViolation[];
|
|
106
|
+
/**
|
|
107
|
+
* Convenience: lint many apps at once, returning a flat list. Each app's
|
|
108
|
+
* violations already carry its `app` label.
|
|
109
|
+
*/
|
|
110
|
+
export declare function lintFiberApps(defs: readonly FiberAppDefinition[]): LintViolation[];
|
|
111
|
+
export {};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical authorization-guard builders — bind "who may act" to the CHAIN-VERIFIED signer of the op,
|
|
3
|
+
* never to an attacker-supplied payload field.
|
|
4
|
+
*
|
|
5
|
+
* The forgeable anti-pattern (security audit class F1): `{"===":[{"var":"event.agent"}, {"var":"state.party"}]}`.
|
|
6
|
+
* The fiber engine injects `event` as the RAW transition payload (ContextProvider: `EVENT -> payload`),
|
|
7
|
+
* so `event.agent` is whatever the submitter wrote — a different party's address forges authorization.
|
|
8
|
+
* The chain ALSO injects `proofs` = `[{address, id, signature}]` where `address = id.toAddress` (the
|
|
9
|
+
* VERIFIED signer addresses). Authorization must bind to THAT. For ASSET ops (mint/burn/morphism) the
|
|
10
|
+
* context has no `event`/`proofs`; it injects `signers` (an array of verified address strings) instead.
|
|
11
|
+
*
|
|
12
|
+
* Use these so the safe pattern is consistent, greppable, and impossible to get subtly wrong.
|
|
13
|
+
*/
|
|
14
|
+
/** A JSON-Logic guard expression (plain JSON). */
|
|
15
|
+
export type GuardRule = Record<string, unknown>;
|
|
16
|
+
/**
|
|
17
|
+
* FIBER-transition authorization: the pinned `partyVar` (a `state` path holding an address, e.g.
|
|
18
|
+
* `"state.borrower"`) MUST be among the op's verified signers (`proofs[].address`). The replay-safe
|
|
19
|
+
* replacement for `{"===":[{"var":"event.agent"}, {"var":partyVar}]}`.
|
|
20
|
+
*/
|
|
21
|
+
export declare const signerIsParty: (partyVar: string) => GuardRule;
|
|
22
|
+
/** FIBER-transition authorization where ANY of the pinned parties signed (e.g. borrower OR lender). */
|
|
23
|
+
export declare const signerIsAnyParty: (partyVars: string[]) => GuardRule;
|
|
24
|
+
/**
|
|
25
|
+
* FIBER-transition authorization where the actor must be a MEMBER of a pinned set: at least one
|
|
26
|
+
* VERIFIED signer is in the `setVar` array (e.g. `"state.signers"`, `"state.members"`, `"state.oracles"`).
|
|
27
|
+
* The replay-safe replacement for `{"in":[{"var":"event.agent"}, {"var":setVar}]}`.
|
|
28
|
+
*/
|
|
29
|
+
export declare const signerInSet: (setVar: string) => GuardRule;
|
|
30
|
+
/**
|
|
31
|
+
* FIBER-transition ANTI-SELF guard: NO verified signer is the pinned party (e.g. a proposal author may
|
|
32
|
+
* not vote on their own proposal). The replay-safe replacement for `{"!==":[{"var":"event.agent"}, {"var":partyVar}]}`.
|
|
33
|
+
*/
|
|
34
|
+
export declare const signerIsNotParty: (partyVar: string) => GuardRule;
|
|
35
|
+
/**
|
|
36
|
+
* FIBER-transition authorization / dedup over a state MAP keyed by address: at least one VERIFIED signer
|
|
37
|
+
* is a key in `mapVar` (e.g. `"state.members"`, `"state.balances"`). The replay-safe replacement for the
|
|
38
|
+
* forgeable `{"getKey":[{"var":mapVar}, {"var":"event.agent"}]}` membership/presence check (note metakit
|
|
39
|
+
* has no `getKey`; use `get`/`has`). For a "no signer has acted yet" dedup, negate: `{"!":[signerHasEntry(...)]}`.
|
|
40
|
+
* For a per-actor VALUE threshold (e.g. balance >= N), build the `some` directly:
|
|
41
|
+
* `{"some":[{"map":[proofs,address]},{">=":[{"get":[mapVar,{"var":""}]}, N]}]}`.
|
|
42
|
+
*/
|
|
43
|
+
export declare const signerHasEntry: (mapVar: string) => GuardRule;
|
|
44
|
+
/**
|
|
45
|
+
* ASSET-op authorization (mintPolicy / burnPolicy / MorphismSpec.guard): the address at `addressVar`
|
|
46
|
+
* (e.g. `"holder.Wallet.address"`) MUST be among the op's verified `signers`. The asset context has no
|
|
47
|
+
* `event` or `proofs` — it injects `signers` directly.
|
|
48
|
+
*/
|
|
49
|
+
export declare const assetSignerIs: (addressVar: string) => GuardRule;
|
|
50
|
+
/**
|
|
51
|
+
* EFFECT-KEY BINDING: prove the event's claimed actor (`actorVar`, default `event.agent`) is a
|
|
52
|
+
* CHAIN-VERIFIED signer, so that field is SAFE to use as a dynamic map key / array element in the
|
|
53
|
+
* EFFECT (`{"set":[map,{"var":"event.agent"},v]}`, `{"cat":[arr,[{"var":"event.agent"}]]}`).
|
|
54
|
+
*
|
|
55
|
+
* This is the coupling clause for the map-write remediation: a guard may authorize via membership /
|
|
56
|
+
* balance / reputation, but if the EFFECT writes under `event.agent` WITHOUT this clause, an attacker
|
|
57
|
+
* sets `event.agent` to a victim's address and writes under the victim's key (security class S1).
|
|
58
|
+
* Pair it with the authorization check expressed on the SAME `actorVar` — together they prove the actor
|
|
59
|
+
* both signed and is authorized, and the effect can only write under that one verified key.
|
|
60
|
+
* Structurally identical to {@link signerIsParty}; named for intent + greppability at write sites.
|
|
61
|
+
*/
|
|
62
|
+
export declare const actorIsSigner: (actorVar?: string) => GuardRule;
|
|
63
|
+
/**
|
|
64
|
+
* EFFECT-KEY-BINDING membership: the event's claimed actor (`actorVar`, default `event.agent`) is BOTH
|
|
65
|
+
* a CHAIN-VERIFIED signer AND a member of the pinned set `setVar` (e.g. `"state.signers"`,
|
|
66
|
+
* `"state.members"`). Use when the EFFECT writes a map/array keyed by that actor and authorization is
|
|
67
|
+
* set-membership. It proves the EXACT actor whose key is written both signed and is authorized — closing
|
|
68
|
+
* the S1 forge AND the subtler gap {@link signerInSet} leaves open: `signerInSet` only proves SOME
|
|
69
|
+
* verified signer is a member, so an op co-signed by an authorized signer could still write a DIFFERENT
|
|
70
|
+
* verified-but-unauthorized address as the key (padding a signature/vote tally). `actorInSet` pins both
|
|
71
|
+
* to the same `actorVar`.
|
|
72
|
+
*/
|
|
73
|
+
export declare const actorInSet: (setVar: string, actorVar?: string) => GuardRule;
|
|
74
|
+
/**
|
|
75
|
+
* EFFECT-KEY-BINDING map membership: the claimed actor (`actorVar`, default `event.agent`) is BOTH a
|
|
76
|
+
* CHAIN-VERIFIED signer AND a key in the pinned state MAP `mapVar` (e.g. `"state.members"`,
|
|
77
|
+
* `"state.balances"`). The map analog of {@link actorInSet} — use it when the membership set is a dict
|
|
78
|
+
* keyed by address, where `in` does not apply and `has` checks key presence. Use when the EFFECT writes
|
|
79
|
+
* `mapVar` (or a per-actor tally) keyed by that actor: it proves the EXACT written key both signed and
|
|
80
|
+
* is an authorized member, closing the vote/signature-stuffing gap that bare {@link signerHasEntry}
|
|
81
|
+
* leaves open (which only proves SOME verified signer is a key, not that the written key is).
|
|
82
|
+
*/
|
|
83
|
+
export declare const actorHasEntry: (mapVar: string, actorVar?: string) => GuardRule;
|
|
84
|
+
/**
|
|
85
|
+
* IDENTITY-REGISTRY reputation gate: at least one VERIFIED signer has a reputation in the registry map
|
|
86
|
+
* at `repMapVar` (a declared-dependency read, e.g. `"machines.<registryDep>.state.reputations"`, shaped
|
|
87
|
+
* `{ <address>: int }`) that is `>=` the bar read from `thresholdVar` (a state path, e.g.
|
|
88
|
+
* `"state.voteThreshold"`). A missing entry reads as null → 0 numerically, so unregistered signers
|
|
89
|
+
* fail-closed for any positive bar. The replay-safe replacement for the forgeable
|
|
90
|
+
* `{">=":[{"var":"event.agentReputation"}, bar]}` (security class S1). See
|
|
91
|
+
* docs/design/app-hardening-identity-integration.md §3–§4.1.
|
|
92
|
+
*/
|
|
93
|
+
export declare const signerHasReputation: (repMapVar: string, thresholdVar: string) => GuardRule;
|
|
94
|
+
/**
|
|
95
|
+
* IDENTITY-REGISTRY role gate: at least one VERIFIED signer holds an active role attestation, i.e. is a
|
|
96
|
+
* key in the registry's flat per-role map at `roleMapVar` (a declared-dependency read, e.g.
|
|
97
|
+
* `"machines.<registryDep>.state.arbiters"` / `".slashers"` / `".issuers"` / `".boardMembers"`, each
|
|
98
|
+
* shaped `{ <address>: true }`). The replay-safe replacement for bare `event.judicialRuling` / role
|
|
99
|
+
* escapes and `{"==":[1,1]}` missing-auth (security class S2). Roles are FLAT per-role maps (not a
|
|
100
|
+
* nested `roles[addr][ROLE]`) because metakit `get`/`has` on a null inner map ERROR rather than
|
|
101
|
+
* returning null; a flat map keeps the read total + fail-closed. See app-hardening §4.2.
|
|
102
|
+
*/
|
|
103
|
+
export declare const signerHasRole: (roleMapVar: string) => GuardRule;
|
|
104
|
+
/**
|
|
105
|
+
* DYNAMIC identity-registry reputation gate — for when the registry instance is bound at RUNTIME via the
|
|
106
|
+
* fiber-engine `_addDependency` directive (#24) rather than hardcoded into the `machines.<uuid>` path.
|
|
107
|
+
* `registryIdVar` is a state/event path holding the registry fiber id (e.g. `"state.registryId"`); the
|
|
108
|
+
* read addresses `machines[<that id>].state.reputations[<signer>]` with dynamic `get`s. Guarded by a
|
|
109
|
+
* presence check so an UNBOUND registry yields a clean `false` (fail-closed) instead of an evaluation
|
|
110
|
+
* error. REQUIRES the registry dependency to have been added in a PRIOR transition (`_addDependency`),
|
|
111
|
+
* because the `machines` context is built before the effect runs (two-phase: bind, then read).
|
|
112
|
+
*/
|
|
113
|
+
export declare const signerHasReputationVia: (registryIdVar: string, thresholdVar: string) => GuardRule;
|
|
114
|
+
/**
|
|
115
|
+
* DYNAMIC identity-registry role gate — the runtime-bound (`_addDependency`, #24) counterpart of
|
|
116
|
+
* {@link signerHasRole}. `registryIdVar` is a state/event path holding the registry fiber id;
|
|
117
|
+
* `roleField` is the registry's flat per-role state map name (`"arbiters"` / `"slashers"` / `"issuers"` /
|
|
118
|
+
* `"boardMembers"` — see REGISTRY_ROLE_MAP). Reads `machines[<id>].state.<roleField>[<signer>]`, guarded
|
|
119
|
+
* by a presence check so an UNBOUND registry yields a clean `false`. Same two-phase requirement as
|
|
120
|
+
* {@link signerHasReputationVia}.
|
|
121
|
+
*/
|
|
122
|
+
export declare const signerHasRoleVia: (registryIdVar: string, roleField: string) => GuardRule;
|
|
123
|
+
/**
|
|
124
|
+
* CROSS-FIBER STATE GATE — assert a RUNTIME-bound dependency fiber is in a required lifecycle state. The
|
|
125
|
+
* replay-safe replacement for the dropped object-form dependency
|
|
126
|
+
* `{machine, instanceRef, requiredState}` (which the chain silently drops — `requiredState` gating never
|
|
127
|
+
* happens). `refVar` is a state/event path holding the dependency's fiber id; reads
|
|
128
|
+
* `machines[<refVar>].currentStateId == requiredState`, guarded by a presence check so an UNBOUND
|
|
129
|
+
* dependency yields a clean `false` (fail-closed). TWO-PHASE (#24): the dependency fiber must have been
|
|
130
|
+
* bound by an `_addDependency` in a PRIOR transition (the `machines` context is built before the effect),
|
|
131
|
+
* so a single gated transition is split into a bind step then this assert step. See
|
|
132
|
+
* docs/design/app-hardening-identity-integration.md §5–§6.
|
|
133
|
+
*/
|
|
134
|
+
/**
|
|
135
|
+
* EFFECT-KEY-BINDING dedup over an ARRAY of records: no existing element of the array at `arrayVar`
|
|
136
|
+
* (e.g. `"state.submissions"`, shaped `[ { addr, value }, … ]`) has its `field` (default `"addr"`)
|
|
137
|
+
* equal to the actor at `actorVar` (default `"event.agent"`). The array analog of the map-keyed
|
|
138
|
+
* `{"!":[has(...)]}` dedup — used where the collection is an append-only array of `{addr,…}` records
|
|
139
|
+
* (there is no `(array,string)` key check, but `none` over the array with a per-element `===` is total).
|
|
140
|
+
*
|
|
141
|
+
* The bare-element callback context inside `none` sees each record map directly, so `{get:[{var:""},field]}`
|
|
142
|
+
* is a valid `(map,string)` read. Pair with an `actorIsSigner`/`actorHasEntry` clause on the same
|
|
143
|
+
* `actorVar` (the dedup proves "not yet present", not "is the verified signer").
|
|
144
|
+
*/
|
|
145
|
+
export declare const actorNotInArray: (arrayVar: string, field?: string, actorVar?: string) => GuardRule;
|
|
146
|
+
export declare const depInState: (refVar: string, requiredState: string) => GuardRule;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DataUpdate Signing Wrappers — dropNulls applied internally
|
|
3
|
+
*
|
|
4
|
+
* Metakit (>= 1.8) computes content hashes by recursively dropping
|
|
5
|
+
* null-valued OBJECT fields (array nulls are preserved) before RFC 8785
|
|
6
|
+
* canonicalization (`JsonBinaryCodec.dropNulls`). This makes
|
|
7
|
+
* `Option = None` indistinguishable from an absent field, so schema
|
|
8
|
+
* evolution never changes prior hashes.
|
|
9
|
+
*
|
|
10
|
+
* The upstream `@constellation-network/metagraph-sdk` signs over the
|
|
11
|
+
* payload as-is, so a payload containing explicit nulls would be signed
|
|
12
|
+
* over different bytes than the metagraph hashes — and the node rejects
|
|
13
|
+
* the signature (HTTP 400).
|
|
14
|
+
*
|
|
15
|
+
* These wrappers shadow the upstream dataUpdate signing surface and apply
|
|
16
|
+
* `dropNulls` internally, unconditionally. Standard-mode signing
|
|
17
|
+
* (currency transactions etc.) is passed through unchanged.
|
|
18
|
+
*/
|
|
19
|
+
import type { SignatureProof, Signed, SigningOptions } from '@constellation-network/metagraph-sdk';
|
|
20
|
+
/**
|
|
21
|
+
* Sign data as a DataUpdate, hashing over null-dropped canonical bytes.
|
|
22
|
+
*
|
|
23
|
+
* Applies `dropNulls` internally so that explicit-null and absent optional
|
|
24
|
+
* fields produce identical signatures, matching metakit's content-hash rule
|
|
25
|
+
* (drop null object fields, preserve array nulls, then RFC 8785).
|
|
26
|
+
*/
|
|
27
|
+
export declare function signDataUpdate<T>(data: T, privateKey: string): SignatureProof;
|
|
28
|
+
/**
|
|
29
|
+
* Create a signed object. In `dataUpdate` mode the signature is computed
|
|
30
|
+
* over the null-dropped canonical bytes (the returned `value` is the
|
|
31
|
+
* caller's original payload, untouched).
|
|
32
|
+
*/
|
|
33
|
+
export declare function createSignedObject<T>(value: T, privateKey: string, options?: SigningOptions): Signed<T>;
|
|
34
|
+
/**
|
|
35
|
+
* Add an additional signature to an existing signed object. In
|
|
36
|
+
* `dataUpdate` mode the new signature is computed over the null-dropped
|
|
37
|
+
* canonical bytes of `signed.value`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function addSignature<T>(signed: Signed<T>, privateKey: string, options?: SigningOptions): Signed<T>;
|
|
40
|
+
/**
|
|
41
|
+
* Create a signed object with multiple signatures at once. In
|
|
42
|
+
* `dataUpdate` mode all signatures are computed over the null-dropped
|
|
43
|
+
* canonical bytes (the returned `value` is the caller's original payload).
|
|
44
|
+
*/
|
|
45
|
+
export declare function batchSign<T>(value: T, privateKeys: string[], options?: SigningOptions): Signed<T>;
|