@calimero-network/mero-js 26.11.0 → 27.0.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/README.md +73 -288
- package/dist/cloud-v2/attestation.d.ts +91 -0
- package/dist/cloud-v2/attestation.js +135 -0
- package/dist/cloud-v2/capabilities.d.ts +30 -0
- package/dist/cloud-v2/capabilities.js +31 -0
- package/dist/cloud-v2/client.d.ts +426 -0
- package/dist/cloud-v2/client.js +646 -0
- package/dist/cloud-v2/errors.d.ts +98 -0
- package/dist/cloud-v2/errors.js +165 -0
- package/dist/cloud-v2/index.d.ts +10 -0
- package/dist/cloud-v2/index.js +5 -0
- package/dist/cloud-v2/passkey.d.ts +27 -0
- package/dist/cloud-v2/passkey.js +73 -0
- package/dist/crypto/internal.d.ts +3 -37
- package/dist/crypto/internal.js +3 -72
- package/dist/index.browser.mjs +4 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +1750 -12772
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +3 -56
- package/dist/index.js +14 -75
- package/dist/index.mjs +1750 -12772
- package/dist/index.mjs.map +4 -4
- package/dist/sealed/index.d.ts +4 -4
- package/dist/sealed/index.js +2 -2
- package/dist/sealed/release.d.ts +21 -76
- package/dist/sealed/release.js +24 -108
- package/dist/sealed/sealed.d.ts +8 -56
- package/dist/sealed/sealed.js +11 -89
- package/dist/sealed/verify.d.ts +7 -13
- package/dist/sealed/verify.js +3 -7
- package/package.json +8 -13
- package/dist/account/account-admin.d.ts +0 -80
- package/dist/account/account-admin.js +0 -346
- package/dist/account/account.d.ts +0 -196
- package/dist/account/account.js +0 -269
- package/dist/account/application-id.d.ts +0 -50
- package/dist/account/application-id.js +0 -83
- package/dist/account/bootstrap-from-invitation.d.ts +0 -110
- package/dist/account/bootstrap-from-invitation.js +0 -80
- package/dist/account/create-context.d.ts +0 -103
- package/dist/account/create-context.js +0 -267
- package/dist/account/govern.d.ts +0 -24
- package/dist/account/govern.js +0 -50
- package/dist/account/index.d.ts +0 -26
- package/dist/account/index.js +0 -15
- package/dist/account/join-as-account.d.ts +0 -23
- package/dist/account/join-as-account.js +0 -34
- package/dist/account/join-with-node.d.ts +0 -115
- package/dist/account/join-with-node.js +0 -161
- package/dist/account/node-admin.d.ts +0 -20
- package/dist/account/node-admin.js +0 -33
- package/dist/account/relay-from-invitation.d.ts +0 -137
- package/dist/account/relay-from-invitation.js +0 -180
- package/dist/account/relay-login-error.d.ts +0 -32
- package/dist/account/relay-login-error.js +0 -34
- package/dist/account/session.d.ts +0 -266
- package/dist/account/session.js +0 -915
- package/dist/account/wordlist.d.ts +0 -16
- package/dist/account/wordlist.js +0 -273
- package/dist/admin-api/admin-client.d.ts +0 -688
- package/dist/admin-api/admin-client.js +0 -1230
- package/dist/admin-api/admin-factory.d.ts +0 -14
- package/dist/admin-api/admin-factory.js +0 -22
- package/dist/admin-api/admin-types.d.ts +0 -2046
- package/dist/admin-api/admin-types.js +0 -12
- package/dist/admin-api/index.d.ts +0 -4
- package/dist/admin-api/index.js +0 -5
- package/dist/admin-api/redeem-invitation.d.ts +0 -101
- package/dist/admin-api/redeem-invitation.js +0 -200
- package/dist/auth/index.d.ts +0 -34
- package/dist/auth/index.js +0 -67
- package/dist/auth-api/auth-client.d.ts +0 -31
- package/dist/auth-api/auth-client.js +0 -117
- package/dist/auth-api/auth-factory.d.ts +0 -7
- package/dist/auth-api/auth-factory.js +0 -41
- package/dist/auth-api/auth-types.d.ts +0 -130
- package/dist/auth-api/auth-types.js +0 -2
- package/dist/auth-api/index.d.ts +0 -3
- package/dist/auth-api/index.js +0 -4
- package/dist/capabilities.d.ts +0 -84
- package/dist/capabilities.js +0 -117
- package/dist/cloud/account-ownership.d.ts +0 -63
- package/dist/cloud/account-ownership.js +0 -87
- package/dist/cloud/cloud-client.d.ts +0 -949
- package/dist/cloud/cloud-client.js +0 -1068
- package/dist/cloud/connect.d.ts +0 -213
- package/dist/cloud/connect.js +0 -260
- package/dist/cloud/enrol-redirect.d.ts +0 -181
- package/dist/cloud/enrol-redirect.js +0 -244
- package/dist/cloud/index.d.ts +0 -12
- package/dist/cloud/index.js +0 -10
- package/dist/cloud/link-redirect.d.ts +0 -95
- package/dist/cloud/link-redirect.js +0 -121
- package/dist/cloud/link-state.d.ts +0 -36
- package/dist/cloud/link-state.js +0 -104
- package/dist/cloud/routing-proof.d.ts +0 -113
- package/dist/cloud/routing-proof.js +0 -96
- package/dist/device-cert/device-cert.d.ts +0 -189
- package/dist/device-cert/device-cert.js +0 -239
- package/dist/device-cert/device-scope.d.ts +0 -58
- package/dist/device-cert/device-scope.js +0 -76
- package/dist/device-cert/index.d.ts +0 -4
- package/dist/device-cert/index.js +0 -3
- package/dist/ephemeral/codec.d.ts +0 -4
- package/dist/ephemeral/codec.js +0 -12
- package/dist/ephemeral/index.d.ts +0 -57
- package/dist/ephemeral/index.js +0 -101
- package/dist/ephemeral/types.d.ts +0 -27
- package/dist/ephemeral/types.js +0 -1
- package/dist/errors/classify.d.ts +0 -65
- package/dist/errors/classify.js +0 -117
- package/dist/errors/index.d.ts +0 -2
- package/dist/errors/index.js +0 -1
- package/dist/events/group.d.ts +0 -95
- package/dist/events/group.js +0 -10
- package/dist/events/index.d.ts +0 -5
- package/dist/events/index.js +0 -2
- package/dist/events/sse.d.ts +0 -127
- package/dist/events/sse.js +0 -469
- package/dist/events/ws.d.ts +0 -57
- package/dist/events/ws.js +0 -212
- package/dist/http-client/api-response.d.ts +0 -15
- package/dist/http-client/api-response.js +0 -1
- package/dist/http-client/http-factory.d.ts +0 -71
- package/dist/http-client/http-factory.js +0 -68
- package/dist/http-client/http-types.d.ts +0 -87
- package/dist/http-client/http-types.js +0 -1
- package/dist/http-client/index.d.ts +0 -7
- package/dist/http-client/index.js +0 -11
- package/dist/http-client/path-segment.d.ts +0 -1
- package/dist/http-client/path-segment.js +0 -8
- package/dist/http-client/retry.d.ts +0 -5
- package/dist/http-client/retry.js +0 -82
- package/dist/http-client/signal-utils.d.ts +0 -2
- package/dist/http-client/signal-utils.js +0 -41
- package/dist/http-client/web-client.d.ts +0 -80
- package/dist/http-client/web-client.js +0 -557
- package/dist/invitation/index.d.ts +0 -2
- package/dist/invitation/index.js +0 -2
- package/dist/invitation/invitation.d.ts +0 -106
- package/dist/invitation/invitation.js +0 -104
- package/dist/login/index.d.ts +0 -4
- package/dist/login/index.js +0 -3
- package/dist/login/login.d.ts +0 -111
- package/dist/login/login.js +0 -110
- package/dist/login/session.d.ts +0 -124
- package/dist/login/session.js +0 -141
- package/dist/mero-js.d.ts +0 -231
- package/dist/mero-js.js +0 -469
- package/dist/namespace-op/index.d.ts +0 -2
- package/dist/namespace-op/index.js +0 -3
- package/dist/namespace-op/namespace-op.d.ts +0 -150
- package/dist/namespace-op/namespace-op.js +0 -191
- package/dist/nodeDiscovery.d.ts +0 -47
- package/dist/nodeDiscovery.js +0 -101
- package/dist/owner-op/index.d.ts +0 -2
- package/dist/owner-op/index.js +0 -3
- package/dist/owner-op/owner-op.d.ts +0 -119
- package/dist/owner-op/owner-op.js +0 -214
- package/dist/presence/relay-presence.d.ts +0 -56
- package/dist/presence/relay-presence.js +0 -107
- package/dist/presence/statement.d.ts +0 -12
- package/dist/presence/statement.js +0 -17
- package/dist/relay/index.d.ts +0 -4
- package/dist/relay/index.js +0 -2
- package/dist/relay/nonce-source.d.ts +0 -72
- package/dist/relay/nonce-source.js +0 -111
- package/dist/relay/relay-client.d.ts +0 -472
- package/dist/relay/relay-client.js +0 -518
- package/dist/relay-attestation/attest-node-key.d.ts +0 -66
- package/dist/relay-attestation/attest-node-key.js +0 -110
- package/dist/relay-attestation/index.d.ts +0 -1
- package/dist/relay-attestation/index.js +0 -1
- package/dist/request/caller-proof.d.ts +0 -43
- package/dist/request/caller-proof.js +0 -36
- package/dist/request/index.d.ts +0 -3
- package/dist/request/index.js +0 -3
- package/dist/request/proof-signer.d.ts +0 -49
- package/dist/request/proof-signer.js +0 -59
- package/dist/request/request-sig.d.ts +0 -99
- package/dist/request/request-sig.js +0 -95
- package/dist/request-proof/authorizer.d.ts +0 -41
- package/dist/request-proof/authorizer.js +0 -60
- package/dist/request-proof/index.d.ts +0 -4
- package/dist/request-proof/index.js +0 -2
- package/dist/request-proof/request-proof.d.ts +0 -53
- package/dist/request-proof/request-proof.js +0 -95
- package/dist/rpc/index.d.ts +0 -64
- package/dist/rpc/index.js +0 -78
- package/dist/signer/index.d.ts +0 -2
- package/dist/signer/index.js +0 -3
- package/dist/signer/signer.d.ts +0 -92
- package/dist/signer/signer.js +0 -147
- package/dist/token-store/index.d.ts +0 -27
- package/dist/token-store/index.js +0 -62
- package/dist/transport/index.d.ts +0 -6
- package/dist/transport/index.js +0 -3
- package/dist/transport/mero-client.d.ts +0 -294
- package/dist/transport/mero-client.js +0 -386
- package/dist/transport/relay-observer.d.ts +0 -152
- package/dist/transport/relay-observer.js +0 -173
- package/dist/transport/relay-transport.d.ts +0 -73
- package/dist/transport/relay-transport.js +0 -94
- package/dist/transport/types.d.ts +0 -100
- package/dist/transport/types.js +0 -32
- package/dist/types/api-response.d.ts +0 -15
- package/dist/types/api-response.js +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.js +0 -1
- package/dist/warrant/creation-warrant.d.ts +0 -163
- package/dist/warrant/creation-warrant.js +0 -194
- package/dist/warrant/governance-op.d.ts +0 -202
- package/dist/warrant/governance-op.js +0 -355
- package/dist/warrant/governance-warrant.d.ts +0 -124
- package/dist/warrant/governance-warrant.js +0 -164
- package/dist/warrant/index.d.ts +0 -8
- package/dist/warrant/index.js +0 -5
- package/dist/warrant/warrant.d.ts +0 -188
- package/dist/warrant/warrant.js +0 -202
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mint a creation warrant: the author's consent for one relay to create one
|
|
3
|
-
* context in one group, once.
|
|
4
|
-
*
|
|
5
|
-
* The intent warrant in `warrant.ts` lets an account with no node *write* to a
|
|
6
|
-
* context; this lets it *create* one. The relay executes the warrant and
|
|
7
|
-
* publishes `GroupOp::ContextRegisteredOnBehalf` carrying it, and every peer
|
|
8
|
-
* checks the **author's** `CAN_CREATE_CONTEXT` (or admin) — the relay needs no
|
|
9
|
-
* create rights of its own, only standing to act for members. The app's `init`
|
|
10
|
-
* runs as the author's account.
|
|
11
|
-
*
|
|
12
|
-
* Same primitives and the same two-widths trap as `warrant.ts`: counts **inside
|
|
13
|
-
* the encoding** are borsh `u32`, counts the **signing preimage** hashes are
|
|
14
|
-
* `u64`. The two `Option<String>` labels add a third shape: on the wire an
|
|
15
|
-
* option is a one-byte tag followed (when present) by a `u32`-prefixed string,
|
|
16
|
-
* while the preimage hashes the tag and the bytes as two separate parts, the
|
|
17
|
-
* bytes empty when absent. That is what keeps `None` and `Some("")` distinct in
|
|
18
|
-
* both.
|
|
19
|
-
*
|
|
20
|
-
* **The byte contract is pinned in core**, at
|
|
21
|
-
* `crates/account/src/tests/creation_wire_fixture.rs`, and this module's test
|
|
22
|
-
* asserts the same vectors. A drift would surface at a relay as a 403.
|
|
23
|
-
*/
|
|
24
|
-
import { type Signer } from '../signer/signer.js';
|
|
25
|
-
/** What a creation warrant authorises. */
|
|
26
|
-
export interface CreationWarrantInput {
|
|
27
|
-
/** The group the context is created in, hex (32 bytes). */
|
|
28
|
-
group: string;
|
|
29
|
-
/**
|
|
30
|
-
* The seed the node derives the new context's id from, hex (32 bytes).
|
|
31
|
-
*
|
|
32
|
-
* Optional: when absent, 32 random bytes are drawn and returned alongside the
|
|
33
|
-
* warrant. Pass one only to make the id predictable — reusing a seed asks for
|
|
34
|
-
* a context that already exists.
|
|
35
|
-
*/
|
|
36
|
-
seed?: string;
|
|
37
|
-
/** The author's account, hex — whose consent this is, and who runs `init`. */
|
|
38
|
-
authorAccount: string;
|
|
39
|
-
/** The relay's account, hex: the subject its authorship grant is held by. */
|
|
40
|
-
executor: string;
|
|
41
|
-
/** The one signing key of `executor` that may carry it out, hex: discovery's `executorKey`. */
|
|
42
|
-
executorKey: string;
|
|
43
|
-
/** The application the context is created with, hex (32 bytes). */
|
|
44
|
-
applicationId: string;
|
|
45
|
-
/**
|
|
46
|
-
* Which service of a multi-service bundle, or absent for the default.
|
|
47
|
-
*
|
|
48
|
-
* Absent and `""` are different values and sign differently. At most 256
|
|
49
|
-
* UTF-8 bytes.
|
|
50
|
-
*/
|
|
51
|
-
serviceName?: string;
|
|
52
|
-
/** A display name for the context, or absent. At most 256 UTF-8 bytes. */
|
|
53
|
-
name?: string;
|
|
54
|
-
/**
|
|
55
|
-
* The JSON the app's `init()` will receive.
|
|
56
|
-
*
|
|
57
|
-
* Committed to rather than carried: the relay is sent the same value
|
|
58
|
-
* separately and the node checks it hashes to what was signed, so pass the
|
|
59
|
-
* exact value you will send. See {@link creationInitHash}.
|
|
60
|
-
*/
|
|
61
|
-
initArgs: unknown;
|
|
62
|
-
/**
|
|
63
|
-
* Monotonic per author **device**. Spent in the *new* context's warrant
|
|
64
|
-
* ledger, so the same per-device nonce source `RelayClient` uses is correct.
|
|
65
|
-
*/
|
|
66
|
-
nonce: number | bigint;
|
|
67
|
-
/** Unix seconds after which the relay must refuse it. */
|
|
68
|
-
notAfter: number | bigint;
|
|
69
|
-
/** Account-log heads the author saw, each hex (32 bytes). At most 64. */
|
|
70
|
-
accountHeads?: string[];
|
|
71
|
-
/**
|
|
72
|
-
* Governance heads the author's view descended from, each hex (32 bytes). At
|
|
73
|
-
* most 64. The same caveat as the intent warrant's floor applies: one the
|
|
74
|
-
* relay supplied is one the relay chose.
|
|
75
|
-
*/
|
|
76
|
-
governanceFloor?: string[];
|
|
77
|
-
/**
|
|
78
|
-
* The author device's ed25519 signing secret, hex (32 bytes). Never sent.
|
|
79
|
-
*
|
|
80
|
-
* Mutually exclusive with {@link CreationWarrantInput.signer}: exactly one is required.
|
|
81
|
-
* Prefer `signer` in a browser, since a secret held as a string is readable
|
|
82
|
-
* by anything on the origin.
|
|
83
|
-
*/
|
|
84
|
-
deviceSecret?: string;
|
|
85
|
-
/**
|
|
86
|
-
* The author device's signer, in place of {@link CreationWarrantInput.deviceSecret}: for a
|
|
87
|
-
* key that cannot be exported to hex (a non-extractable WebCrypto key, a
|
|
88
|
-
* passkey, a hardware or remote signer). Its `publicKey` becomes the
|
|
89
|
-
* warrant's `author_device_key`, and it signs the 32-byte preimage as is.
|
|
90
|
-
*/
|
|
91
|
-
signer?: Signer;
|
|
92
|
-
}
|
|
93
|
-
/** A signed creation warrant and the seed it commits to. */
|
|
94
|
-
export interface SignedCreationWarrant {
|
|
95
|
-
/** Hex borsh `ContextCreationWarrant`, ready for the relay. */
|
|
96
|
-
warrant: string;
|
|
97
|
-
/** The seed, hex — the one passed in, or the one drawn when none was. */
|
|
98
|
-
seed: string;
|
|
99
|
-
}
|
|
100
|
-
/** A creation warrant's fields, decoded from the wire encoding. */
|
|
101
|
-
export interface CreationWarrantFields {
|
|
102
|
-
group: string;
|
|
103
|
-
seed: string;
|
|
104
|
-
authorAccount: string;
|
|
105
|
-
/** The author device key: the signer's public key. */
|
|
106
|
-
deviceKey: string;
|
|
107
|
-
executor: string;
|
|
108
|
-
executorKey: string;
|
|
109
|
-
applicationId: string;
|
|
110
|
-
/** `null` when absent — distinct from `""`. */
|
|
111
|
-
serviceName: string | null;
|
|
112
|
-
/** `null` when absent — distinct from `""`. */
|
|
113
|
-
name: string | null;
|
|
114
|
-
initHash: string;
|
|
115
|
-
accountHeads: string[];
|
|
116
|
-
governanceFloor: string[];
|
|
117
|
-
nonce: bigint;
|
|
118
|
-
notAfter: bigint;
|
|
119
|
-
signature: string;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* The commitment a creation warrant carries in place of the init arguments.
|
|
123
|
-
*
|
|
124
|
-
* Hashes `JSON.stringify(initArgs)`, the same bytes `RelayClient.createContext`
|
|
125
|
-
* sends, under its own domain.
|
|
126
|
-
*/
|
|
127
|
-
export declare function creationInitHash(initArgs: unknown): Promise<Uint8Array>;
|
|
128
|
-
/** The already-decoded fields the signature covers. Internal. */
|
|
129
|
-
export interface CreationPreimageParts {
|
|
130
|
-
group: Uint8Array;
|
|
131
|
-
seed: Uint8Array;
|
|
132
|
-
authorAccount: Uint8Array;
|
|
133
|
-
deviceKey: Uint8Array;
|
|
134
|
-
executor: Uint8Array;
|
|
135
|
-
executorKey: Uint8Array;
|
|
136
|
-
applicationId: Uint8Array;
|
|
137
|
-
serviceName: Uint8Array | null;
|
|
138
|
-
name: Uint8Array | null;
|
|
139
|
-
initHash: Uint8Array;
|
|
140
|
-
accountHeads: Uint8Array[];
|
|
141
|
-
governanceFloor: Uint8Array[];
|
|
142
|
-
nonce: number | bigint;
|
|
143
|
-
notAfter: number | bigint;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* The bytes the device key signs. Exported for the conformance test only — not
|
|
147
|
-
* from the package root.
|
|
148
|
-
*/
|
|
149
|
-
export declare function creationWarrantPreimage(p: CreationPreimageParts): Promise<Uint8Array>;
|
|
150
|
-
/**
|
|
151
|
-
* Sign a creation warrant and return it hex-encoded, with its seed.
|
|
152
|
-
*
|
|
153
|
-
* Returns the encoding rather than an object for the reason `signWarrant`
|
|
154
|
-
* does: the signature covers exactly these bytes.
|
|
155
|
-
*/
|
|
156
|
-
export declare function signCreationWarrant(input: CreationWarrantInput): Promise<SignedCreationWarrant>;
|
|
157
|
-
/**
|
|
158
|
-
* Decode a hex creation warrant back into its fields.
|
|
159
|
-
*
|
|
160
|
-
* Refuses truncated or trailing bytes rather than reading a neighbouring field.
|
|
161
|
-
* Does not verify the signature.
|
|
162
|
-
*/
|
|
163
|
-
export declare function parseCreationWarrant(warrant: string): CreationWarrantFields;
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mint a creation warrant: the author's consent for one relay to create one
|
|
3
|
-
* context in one group, once.
|
|
4
|
-
*
|
|
5
|
-
* The intent warrant in `warrant.ts` lets an account with no node *write* to a
|
|
6
|
-
* context; this lets it *create* one. The relay executes the warrant and
|
|
7
|
-
* publishes `GroupOp::ContextRegisteredOnBehalf` carrying it, and every peer
|
|
8
|
-
* checks the **author's** `CAN_CREATE_CONTEXT` (or admin) — the relay needs no
|
|
9
|
-
* create rights of its own, only standing to act for members. The app's `init`
|
|
10
|
-
* runs as the author's account.
|
|
11
|
-
*
|
|
12
|
-
* Same primitives and the same two-widths trap as `warrant.ts`: counts **inside
|
|
13
|
-
* the encoding** are borsh `u32`, counts the **signing preimage** hashes are
|
|
14
|
-
* `u64`. The two `Option<String>` labels add a third shape: on the wire an
|
|
15
|
-
* option is a one-byte tag followed (when present) by a `u32`-prefixed string,
|
|
16
|
-
* while the preimage hashes the tag and the bytes as two separate parts, the
|
|
17
|
-
* bytes empty when absent. That is what keeps `None` and `Some("")` distinct in
|
|
18
|
-
* both.
|
|
19
|
-
*
|
|
20
|
-
* **The byte contract is pinned in core**, at
|
|
21
|
-
* `crates/account/src/tests/creation_wire_fixture.rs`, and this module's test
|
|
22
|
-
* asserts the same vectors. A drift would surface at a relay as a 403.
|
|
23
|
-
*/
|
|
24
|
-
import { concat, domainHash, fromHex, hex, u32le, u64le } from '../crypto/internal.js';
|
|
25
|
-
import { resolveSigner } from '../signer/signer.js';
|
|
26
|
-
import { checkedSignature, citedHeads } from './warrant.js';
|
|
27
|
-
const SIGN_DOMAIN = new TextEncoder().encode('calimero.context-creation-warrant.v1');
|
|
28
|
-
const INIT_DOMAIN = new TextEncoder().encode('calimero.context-creation.init.v1');
|
|
29
|
-
/** core's cap on `service_name` and `name`, in UTF-8 bytes. */
|
|
30
|
-
const MAX_LABEL_BYTES = 256;
|
|
31
|
-
/**
|
|
32
|
-
* The commitment a creation warrant carries in place of the init arguments.
|
|
33
|
-
*
|
|
34
|
-
* Hashes `JSON.stringify(initArgs)`, the same bytes `RelayClient.createContext`
|
|
35
|
-
* sends, under its own domain.
|
|
36
|
-
*/
|
|
37
|
-
export async function creationInitHash(initArgs) {
|
|
38
|
-
const bytes = new TextEncoder().encode(JSON.stringify(initArgs));
|
|
39
|
-
return domainHash(INIT_DOMAIN, [bytes]);
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* The bytes the device key signs. Exported for the conformance test only — not
|
|
43
|
-
* from the package root.
|
|
44
|
-
*/
|
|
45
|
-
export async function creationWarrantPreimage(p) {
|
|
46
|
-
// An option is two parts here — its tag, then its bytes (empty when absent) —
|
|
47
|
-
// so `None` and `Some("")` hash differently. u64 counts HERE; u32 on the wire.
|
|
48
|
-
return domainHash(SIGN_DOMAIN, [
|
|
49
|
-
p.group,
|
|
50
|
-
p.seed,
|
|
51
|
-
p.authorAccount,
|
|
52
|
-
p.deviceKey,
|
|
53
|
-
p.executor,
|
|
54
|
-
p.executorKey,
|
|
55
|
-
p.applicationId,
|
|
56
|
-
new Uint8Array([p.serviceName === null ? 0 : 1]),
|
|
57
|
-
p.serviceName ?? new Uint8Array(0),
|
|
58
|
-
new Uint8Array([p.name === null ? 0 : 1]),
|
|
59
|
-
p.name ?? new Uint8Array(0),
|
|
60
|
-
p.initHash,
|
|
61
|
-
u64le(p.accountHeads.length),
|
|
62
|
-
...p.accountHeads,
|
|
63
|
-
u64le(p.governanceFloor.length),
|
|
64
|
-
...p.governanceFloor,
|
|
65
|
-
u64le(p.nonce),
|
|
66
|
-
u64le(p.notAfter),
|
|
67
|
-
]);
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Sign a creation warrant and return it hex-encoded, with its seed.
|
|
71
|
-
*
|
|
72
|
-
* Returns the encoding rather than an object for the reason `signWarrant`
|
|
73
|
-
* does: the signature covers exactly these bytes.
|
|
74
|
-
*/
|
|
75
|
-
export async function signCreationWarrant(input) {
|
|
76
|
-
const group = fromHex(input.group, 'group', 32);
|
|
77
|
-
const seed = input.seed === undefined
|
|
78
|
-
? crypto.getRandomValues(new Uint8Array(32))
|
|
79
|
-
: fromHex(input.seed, 'seed', 32);
|
|
80
|
-
const authorAccount = fromHex(input.authorAccount, 'authorAccount', 32);
|
|
81
|
-
const executor = fromHex(input.executor, 'executor', 32);
|
|
82
|
-
const executorKey = fromHex(input.executorKey, 'executorKey', 32);
|
|
83
|
-
const applicationId = fromHex(input.applicationId, 'applicationId', 32);
|
|
84
|
-
const serviceName = label(input.serviceName, 'serviceName');
|
|
85
|
-
const name = label(input.name, 'name');
|
|
86
|
-
const accountHeads = citedHeads(input.accountHeads, 'accountHeads');
|
|
87
|
-
const governanceFloor = citedHeads(input.governanceFloor, 'governanceFloor');
|
|
88
|
-
const signer = await resolveSigner(input.deviceSecret, input.signer, 'deviceSecret');
|
|
89
|
-
const deviceKey = fromHex(signer.publicKey, 'signer.publicKey', 32);
|
|
90
|
-
const initHash = await creationInitHash(input.initArgs);
|
|
91
|
-
const preimage = await creationWarrantPreimage({
|
|
92
|
-
group,
|
|
93
|
-
seed,
|
|
94
|
-
authorAccount,
|
|
95
|
-
deviceKey,
|
|
96
|
-
executor,
|
|
97
|
-
executorKey,
|
|
98
|
-
applicationId,
|
|
99
|
-
serviceName,
|
|
100
|
-
name,
|
|
101
|
-
initHash,
|
|
102
|
-
accountHeads,
|
|
103
|
-
governanceFloor,
|
|
104
|
-
nonce: input.nonce,
|
|
105
|
-
notAfter: input.notAfter,
|
|
106
|
-
});
|
|
107
|
-
const signature = checkedSignature(await signer.sign(preimage));
|
|
108
|
-
const warrant = hex(concat(group, seed, authorAccount, deviceKey, executor, executorKey, applicationId, borshOption(serviceName), borshOption(name), initHash, u32le(accountHeads.length), ...accountHeads, u32le(governanceFloor.length), ...governanceFloor, u64le(input.nonce), u64le(input.notAfter), signature));
|
|
109
|
-
return { warrant, seed: hex(seed) };
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Decode a hex creation warrant back into its fields.
|
|
113
|
-
*
|
|
114
|
-
* Refuses truncated or trailing bytes rather than reading a neighbouring field.
|
|
115
|
-
* Does not verify the signature.
|
|
116
|
-
*/
|
|
117
|
-
export function parseCreationWarrant(warrant) {
|
|
118
|
-
const clean = warrant.trim();
|
|
119
|
-
if (!/^[0-9a-fA-F]*$/.test(clean) || clean.length % 2 !== 0) {
|
|
120
|
-
throw new Error('creation warrant must be an even number of hex characters');
|
|
121
|
-
}
|
|
122
|
-
const bytes = new Uint8Array(clean.length / 2);
|
|
123
|
-
for (let i = 0; i < bytes.length; i += 1) {
|
|
124
|
-
bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
125
|
-
}
|
|
126
|
-
const view = new DataView(bytes.buffer);
|
|
127
|
-
let o = 0;
|
|
128
|
-
const take = (n, what) => {
|
|
129
|
-
if (o + n > bytes.length) {
|
|
130
|
-
throw new Error(`creation warrant ends inside ${what} (${bytes.length} bytes)`);
|
|
131
|
-
}
|
|
132
|
-
const out = bytes.subarray(o, o + n);
|
|
133
|
-
o += n;
|
|
134
|
-
return out;
|
|
135
|
-
};
|
|
136
|
-
const u32 = (what) => view.getUint32(take(4, what).byteOffset, true);
|
|
137
|
-
const u64 = (what) => view.getBigUint64(take(8, what).byteOffset, true);
|
|
138
|
-
const option = (what) => {
|
|
139
|
-
const tag = take(1, what)[0];
|
|
140
|
-
if (tag === 0)
|
|
141
|
-
return null;
|
|
142
|
-
if (tag !== 1)
|
|
143
|
-
throw new Error(`${what} has option tag ${tag}, expected 0 or 1`);
|
|
144
|
-
const len = u32(what);
|
|
145
|
-
if (len > MAX_LABEL_BYTES) {
|
|
146
|
-
throw new Error(`${what} is ${len} bytes, over the ${MAX_LABEL_BYTES} a node accepts`);
|
|
147
|
-
}
|
|
148
|
-
return new TextDecoder('utf-8', { fatal: true }).decode(take(len, what));
|
|
149
|
-
};
|
|
150
|
-
const heads = (what) => {
|
|
151
|
-
const count = u32(what);
|
|
152
|
-
if (count > 64) {
|
|
153
|
-
throw new Error(`${what} cites ${count} heads, over the 64 a node accepts`);
|
|
154
|
-
}
|
|
155
|
-
return Array.from({ length: count }, () => hex(take(32, what)));
|
|
156
|
-
};
|
|
157
|
-
const fields = {
|
|
158
|
-
group: hex(take(32, 'group')),
|
|
159
|
-
seed: hex(take(32, 'seed')),
|
|
160
|
-
authorAccount: hex(take(32, 'authorAccount')),
|
|
161
|
-
deviceKey: hex(take(32, 'deviceKey')),
|
|
162
|
-
executor: hex(take(32, 'executor')),
|
|
163
|
-
executorKey: hex(take(32, 'executorKey')),
|
|
164
|
-
applicationId: hex(take(32, 'applicationId')),
|
|
165
|
-
serviceName: option('serviceName'),
|
|
166
|
-
name: option('name'),
|
|
167
|
-
initHash: hex(take(32, 'initHash')),
|
|
168
|
-
accountHeads: heads('accountHeads'),
|
|
169
|
-
governanceFloor: heads('governanceFloor'),
|
|
170
|
-
nonce: u64('nonce'),
|
|
171
|
-
notAfter: u64('notAfter'),
|
|
172
|
-
signature: hex(take(64, 'signature')),
|
|
173
|
-
};
|
|
174
|
-
if (o !== bytes.length) {
|
|
175
|
-
throw new Error(`creation warrant is ${bytes.length} bytes but its fields account for ${o}`);
|
|
176
|
-
}
|
|
177
|
-
return fields;
|
|
178
|
-
}
|
|
179
|
-
/** UTF-8 encode an optional label, refusing one longer than a node accepts. */
|
|
180
|
-
function label(value, what) {
|
|
181
|
-
if (value === undefined)
|
|
182
|
-
return null;
|
|
183
|
-
const bytes = new TextEncoder().encode(value);
|
|
184
|
-
if (bytes.length > MAX_LABEL_BYTES) {
|
|
185
|
-
throw new Error(`${what} is ${bytes.length} UTF-8 bytes, over the ${MAX_LABEL_BYTES} a node accepts`);
|
|
186
|
-
}
|
|
187
|
-
return bytes;
|
|
188
|
-
}
|
|
189
|
-
/** Borsh `Option<String>`: `0x00`, or `0x01` then a u32 length and the bytes. */
|
|
190
|
-
function borshOption(bytes) {
|
|
191
|
-
if (bytes === null)
|
|
192
|
-
return new Uint8Array([0]);
|
|
193
|
-
return concat(new Uint8Array([1]), u32le(bytes.length), bytes);
|
|
194
|
-
}
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Encode the governance ops a member may have a relay publish for them.
|
|
3
|
-
*
|
|
4
|
-
* A governance warrant commits to an op's **borsh bytes**, not to a description
|
|
5
|
-
* of it, so the client has to produce exactly the bytes the node decodes. These
|
|
6
|
-
* encoders cover the delegable ops (core's `GroupOp::delegable_form` and
|
|
7
|
-
* `RootOp::delegable_form`) that a keyholder app is likely to need. Every
|
|
8
|
-
* discriminant is a variant's position in core's enum, which is how borsh
|
|
9
|
-
* encodes a Rust enum; they are pinned against core's own vectors in the test.
|
|
10
|
-
*
|
|
11
|
-
* **Delegable form.** A removal, a leave and a cascade delete carry fields only
|
|
12
|
-
* the publisher can compute (post-state hashes, the enumerated subtree). The
|
|
13
|
-
* member signs them cleared, and these encoders only ever produce the cleared
|
|
14
|
-
* form, which is the one a relay accepts. The relay fills them in afterwards.
|
|
15
|
-
*
|
|
16
|
-
* Sources in core, for the next person to check a discriminant:
|
|
17
|
-
* `crates/governance-types/src/lib.rs` (`GroupOp`, `RootOp`),
|
|
18
|
-
* `crates/primitives/src/context.rs` (`GroupMemberRole`),
|
|
19
|
-
* `crates/account/src/namespace_id.rs` (`founded_namespace_id`), and the vectors in
|
|
20
|
-
* `crates/governance-types/src/tests.rs` (`delegated_governance_op_vectors_are_stable`).
|
|
21
|
-
*/
|
|
22
|
-
/**
|
|
23
|
-
* Which plane an op is published on: `group` is a `GroupOp` on the group's own
|
|
24
|
-
* log, `root` a `RootOp` on the namespace log. The kind is signed over, so
|
|
25
|
-
* consent to one can never be presented as the other.
|
|
26
|
-
*/
|
|
27
|
-
export type GovernanceOpKind = 'group' | 'root';
|
|
28
|
-
/** An encoded governance op and the plane it belongs to. */
|
|
29
|
-
export interface GovernanceOp {
|
|
30
|
-
kind: GovernanceOpKind;
|
|
31
|
-
/** The op's borsh bytes in delegable form: what the warrant commits to. */
|
|
32
|
-
bytes: Uint8Array;
|
|
33
|
-
}
|
|
34
|
-
/** A group member's role. Borsh discriminants follow core's `GroupMemberRole`. */
|
|
35
|
-
export type GovernanceMemberRole = 'Admin' | 'Member' | 'ReadOnly';
|
|
36
|
-
/**
|
|
37
|
-
* Add `member` (an account, hex) to the group with `role`.
|
|
38
|
-
*
|
|
39
|
-
* Applied as the author: adding a `Member` needs `MANAGE_MEMBERS` or admin,
|
|
40
|
-
* adding an `Admin` needs admin.
|
|
41
|
-
*/
|
|
42
|
-
export declare function memberAddedOp(member: string, memberRole: GovernanceMemberRole): GovernanceOp;
|
|
43
|
-
/**
|
|
44
|
-
* Remove `member` (an account, hex) from the group, in delegable form: both
|
|
45
|
-
* post-state claims cleared, for the relay to compute from its own view.
|
|
46
|
-
*/
|
|
47
|
-
export declare function memberRemovedOp(member: string): GovernanceOp;
|
|
48
|
-
/**
|
|
49
|
-
* The author leaves the group, in delegable form. The node applies it only when
|
|
50
|
-
* `member` is the author's own account.
|
|
51
|
-
*/
|
|
52
|
-
export declare function memberLeftOp(member: string): GovernanceOp;
|
|
53
|
-
/** Set `member`'s role (an account, hex). */
|
|
54
|
-
export declare function memberRoleSetOp(member: string, memberRole: GovernanceMemberRole): GovernanceOp;
|
|
55
|
-
/**
|
|
56
|
-
* The id `admin` derives for a subgroup under `parentId` with birth visibility
|
|
57
|
-
* `restricted` and `salt` (all hex), as core's `created_subgroup_id` does:
|
|
58
|
-
* `domain_hash("calimero.subgroup.id.v1", [admin, parentId, [restricted], salt])`.
|
|
59
|
-
*
|
|
60
|
-
* A subgroup's id is bound to its create, so nobody but its creator can name
|
|
61
|
-
* it: a node refuses a `GroupCreated` whose fields do not reproduce its id.
|
|
62
|
-
* That is what stops a second member racing a concurrent create for an id it
|
|
63
|
-
* saw gossiped.
|
|
64
|
-
*/
|
|
65
|
-
export declare function createdSubgroupId(admin: string, parentId: string, restricted: boolean, salt: string): Promise<string>;
|
|
66
|
-
/**
|
|
67
|
-
* Choose the application a group runs (`GroupOp::TargetApplicationSet`), in
|
|
68
|
-
* its delegable form: `bytecode_id` is left for the relay to fill (32 zero
|
|
69
|
-
* bytes), resolved from `package@version` in the registry. The member signs
|
|
70
|
-
* the application id, package and version, so the relay can pick no other
|
|
71
|
-
* build; the application id binds package and signer, and every node checks
|
|
72
|
-
* the bundle's signature.
|
|
73
|
-
*
|
|
74
|
-
* Through a relay this is accepted only as a group's FIRST application, on a
|
|
75
|
-
* group that targets none yet (a namespace an account founded). Moving an
|
|
76
|
-
* existing target is an upgrade, which never goes through a relay.
|
|
77
|
-
*/
|
|
78
|
-
export declare function targetApplicationSetOp(input: {
|
|
79
|
-
applicationId: string;
|
|
80
|
-
package: string;
|
|
81
|
-
version: string;
|
|
82
|
-
}): GovernanceOp;
|
|
83
|
-
export declare function defaultCapabilitiesSetOp(capabilities: number): GovernanceOp;
|
|
84
|
-
/** What a subgroup is created with. */
|
|
85
|
-
export interface GroupCreatedInput {
|
|
86
|
-
/**
|
|
87
|
-
* The new subgroup's id, hex (32 bytes). It must be
|
|
88
|
-
* `createdSubgroupId(admin, parentId, restricted, salt)`; a node refuses any
|
|
89
|
-
* other. {@link subgroupCreation} draws the salt and derives it for you.
|
|
90
|
-
*/
|
|
91
|
-
groupId: string;
|
|
92
|
-
/** The group it is nested under, hex: the namespace root or an existing subgroup. */
|
|
93
|
-
parentId: string;
|
|
94
|
-
/** `true` for a Restricted subgroup, `false` for born-Open (the default). */
|
|
95
|
-
restricted: boolean;
|
|
96
|
-
/**
|
|
97
|
-
* The subgroup's founding admin, hex: the **author's** account. The node
|
|
98
|
-
* refuses any other, since the op is applied as the author.
|
|
99
|
-
*/
|
|
100
|
-
admin: string;
|
|
101
|
-
/** The salt `groupId` was derived with, hex (32 bytes). Random; need not be kept. */
|
|
102
|
-
salt: string;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Create a subgroup under `parentId`, a root op published on the namespace.
|
|
106
|
-
*
|
|
107
|
-
* Needs `CAN_CREATE_SUBGROUP` or admin on the parent; the author, not the
|
|
108
|
-
* relay, becomes the new subgroup's admin.
|
|
109
|
-
*/
|
|
110
|
-
export declare function groupCreatedOp(input: GroupCreatedInput): GovernanceOp;
|
|
111
|
-
/** A new subgroup's create: its derived id, the salt it was derived with, and the op. */
|
|
112
|
-
export interface SubgroupCreation {
|
|
113
|
-
groupId: string;
|
|
114
|
-
salt: string;
|
|
115
|
-
op: GovernanceOp;
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Create a subgroup under `parentId`: draws a fresh salt (unless one is given),
|
|
119
|
-
* derives the id with {@link createdSubgroupId}, and encodes the op.
|
|
120
|
-
*/
|
|
121
|
-
export declare function subgroupCreation(input: Omit<GroupCreatedInput, 'groupId' | 'salt'> & {
|
|
122
|
-
salt?: string;
|
|
123
|
-
}): Promise<SubgroupCreation>;
|
|
124
|
-
/** Move `childGroupId` under `newParentId`, a root op. */
|
|
125
|
-
export declare function groupReparentedOp(childGroupId: string, newParentId: string): GovernanceOp;
|
|
126
|
-
/**
|
|
127
|
-
* Delete `rootGroupId` and its subtree, in delegable form: both cascade lists
|
|
128
|
-
* empty, for the relay to enumerate.
|
|
129
|
-
*/
|
|
130
|
-
export declare function groupDeletedOp(rootGroupId: string): GovernanceOp;
|
|
131
|
-
/**
|
|
132
|
-
* The id of the namespace `founder` founds with `salt`: core's
|
|
133
|
-
* `founded_namespace_id`, `domain_hash("calimero.namespace.id.v1", [founder, salt])`.
|
|
134
|
-
*
|
|
135
|
-
* Anyone holding the pair can recompute it, and only the founder's account
|
|
136
|
-
* hashes to it, which is why a relay founding a namespace for a member cannot
|
|
137
|
-
* choose the id: the member computes it and signs it.
|
|
138
|
-
*/
|
|
139
|
-
export declare function foundedNamespaceId(founder: string, salt: string): Promise<string>;
|
|
140
|
-
/** What a namespace is founded with. */
|
|
141
|
-
export interface NamespaceCreatedInput {
|
|
142
|
-
/** The founding account, hex: the **author's**. It becomes founder, owner and admin. */
|
|
143
|
-
founder: string;
|
|
144
|
-
/**
|
|
145
|
-
* The founder's `AccountProof<DeviceCert>`, hex: the credential the author
|
|
146
|
-
* already presents as `authorProof`. Its account must be `founder` and its
|
|
147
|
-
* device key the one that signs the warrant; the genesis apply checks both
|
|
148
|
-
* and binds the founder's device from it.
|
|
149
|
-
*/
|
|
150
|
-
credential: string;
|
|
151
|
-
/**
|
|
152
|
-
* The salt the namespace id is derived with, hex (32 bytes). Choose it at
|
|
153
|
-
* random; {@link foundedNamespaceId} gives the id it yields.
|
|
154
|
-
*/
|
|
155
|
-
salt: string;
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Found a namespace: core's `RootOp::NamespaceCreatedV2` genesis, a root op
|
|
159
|
-
* published on the new namespace's own log.
|
|
160
|
-
*
|
|
161
|
-
* Its delegable form is the op itself, nothing cleared, so the author signs the
|
|
162
|
-
* exact genesis. Borsh is `[9] || founder || credential || salt`: the credential
|
|
163
|
-
* is a nested struct, not a length-prefixed byte string, so it is written
|
|
164
|
-
* inline. The warrant's scope must be {@link foundedNamespaceId}`(founder, salt)`.
|
|
165
|
-
*/
|
|
166
|
-
export declare function namespaceCreatedOp(input: NamespaceCreatedInput): GovernanceOp;
|
|
167
|
-
/** Set `member`'s capabilities in the group (`GroupOp::MemberCapabilitySet`). Bit 9 is refused. */
|
|
168
|
-
export declare function memberCapabilitySetOp(member: string, capabilities: number): GovernanceOp;
|
|
169
|
-
/** Detach a context from the group (`GroupOp::ContextDetached`). */
|
|
170
|
-
export declare function contextDetachedOp(contextId: string): GovernanceOp;
|
|
171
|
-
/** Make a subgroup open (members of the parent may join it themselves) or restricted. */
|
|
172
|
-
export declare function subgroupVisibilitySetOp(mode: 'open' | 'restricted'): GovernanceOp;
|
|
173
|
-
/** Name the group, with optional key/value data (`GroupOp::GroupMetadataSet`). */
|
|
174
|
-
export declare function groupMetadataSetOp(input?: {
|
|
175
|
-
name?: string;
|
|
176
|
-
data?: Record<string, string>;
|
|
177
|
-
}): GovernanceOp;
|
|
178
|
-
/** Name a member in the group (`GroupOp::MemberMetadataSet`). */
|
|
179
|
-
export declare function memberMetadataSetOp(member: string, input?: {
|
|
180
|
-
name?: string;
|
|
181
|
-
data?: Record<string, string>;
|
|
182
|
-
}): GovernanceOp;
|
|
183
|
-
/** Name a context in the group (`GroupOp::ContextMetadataSet`). */
|
|
184
|
-
export declare function contextMetadataSetOp(contextId: string, input?: {
|
|
185
|
-
name?: string;
|
|
186
|
-
data?: Record<string, string>;
|
|
187
|
-
}): GovernanceOp;
|
|
188
|
-
/** Grant `member` a per-context capability (`GroupOp::ContextCapabilityGranted`). */
|
|
189
|
-
export declare function contextCapabilityGrantedOp(contextId: string, member: string, capability: number): GovernanceOp;
|
|
190
|
-
/** Revoke a per-context capability from `member` (`GroupOp::ContextCapabilityRevoked`). */
|
|
191
|
-
export declare function contextCapabilityRevokedOp(contextId: string, member: string, capability: number): GovernanceOp;
|
|
192
|
-
/**
|
|
193
|
-
* Join an open subgroup yourself (`RootOp::MemberJoinedOpen`), a root op posted
|
|
194
|
-
* to the namespace. `member` must be the author; `credential` is the author's
|
|
195
|
-
* own `AccountProof<DeviceCert>`, hex, carried as-is. The author's
|
|
196
|
-
* `CAN_JOIN_OPEN_SUBGROUPS` and the open inheritance path are checked as usual.
|
|
197
|
-
*/
|
|
198
|
-
export declare function memberJoinedOpenOp(input: {
|
|
199
|
-
member: string;
|
|
200
|
-
groupId: string;
|
|
201
|
-
credential: string;
|
|
202
|
-
}): GovernanceOp;
|