@serfab/cadre-core 1.13.0 → 1.15.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 +293 -274
- package/dist/cadre-invite-protocol.d.ts +383 -0
- package/dist/cadre-invite-protocol.js +774 -0
- package/dist/cadre-invite-protocol.js.map +1 -0
- package/dist/cadre-join-request.d.ts +42 -0
- package/dist/cadre-join-request.js +144 -0
- package/dist/cadre-join-request.js.map +1 -0
- package/dist/cadre-node.d.ts +849 -210
- package/dist/cadre-node.js +1574 -374
- package/dist/cadre-node.js.map +1 -1
- package/dist/claim-proof.d.ts +45 -0
- package/dist/claim-proof.js +132 -0
- package/dist/claim-proof.js.map +1 -0
- package/dist/control-authorization.d.ts +80 -19
- package/dist/control-authorization.js +55 -13
- package/dist/control-authorization.js.map +1 -1
- package/dist/control-cohort.js +1 -1
- package/dist/control-cohort.js.map +1 -1
- package/dist/control-database.d.ts +605 -108
- package/dist/control-database.js +1299 -280
- package/dist/control-database.js.map +1 -1
- package/dist/control-protocol-guard.d.ts +142 -0
- package/dist/control-protocol-guard.js +293 -0
- package/dist/control-protocol-guard.js.map +1 -0
- package/dist/control-schema.d.ts +1 -1
- package/dist/control-schema.js +817 -1067
- package/dist/control-schema.js.map +1 -1
- package/dist/control-stream.d.ts +4 -0
- package/dist/control-stream.js +22 -7
- package/dist/control-stream.js.map +1 -1
- package/dist/delegate-admission.d.ts +1 -1
- package/dist/delegate-admission.js +1 -1
- package/dist/device-token.d.ts +11 -9
- package/dist/device-token.js +14 -12
- package/dist/device-token.js.map +1 -1
- package/dist/ed25519-key.d.ts +22 -9
- package/dist/ed25519-key.js +47 -10
- package/dist/ed25519-key.js.map +1 -1
- package/dist/fetch-impl.d.ts +12 -0
- package/dist/fetch-impl.js +23 -0
- package/dist/fetch-impl.js.map +1 -0
- package/dist/file-durable-slot.js +2 -1
- package/dist/file-durable-slot.js.map +1 -1
- package/dist/file-safe-name.d.ts +25 -0
- package/dist/file-safe-name.js +29 -0
- package/dist/file-safe-name.js.map +1 -0
- package/dist/formation-approval.js +5 -11
- package/dist/formation-approval.js.map +1 -1
- package/dist/fs-atomic.d.ts +0 -19
- package/dist/fs-atomic.js +3 -24
- package/dist/fs-atomic.js.map +1 -1
- package/dist/index.d.ts +22 -10
- package/dist/index.js +54 -11
- package/dist/index.js.map +1 -1
- package/dist/invitation-bootstrap.d.ts +50 -12
- package/dist/invitation-bootstrap.js +76 -13
- package/dist/invitation-bootstrap.js.map +1 -1
- package/dist/joined-strand-store.d.ts +7 -0
- package/dist/joined-strand-store.js +9 -0
- package/dist/joined-strand-store.js.map +1 -1
- package/dist/key-store-file.js +2 -1
- package/dist/key-store-file.js.map +1 -1
- package/dist/link-budget.d.ts +25 -33
- package/dist/link-budget.js +25 -35
- package/dist/link-budget.js.map +1 -1
- package/dist/machine-removal.d.ts +78 -0
- package/dist/machine-removal.js +166 -0
- package/dist/machine-removal.js.map +1 -0
- package/dist/membership-connection-gater.d.ts +191 -151
- package/dist/membership-connection-gater.js +236 -173
- package/dist/membership-connection-gater.js.map +1 -1
- package/dist/node-claim-payload.d.ts +74 -0
- package/dist/node-claim-payload.js +224 -0
- package/dist/node-claim-payload.js.map +1 -0
- package/dist/node-default-transports.d.ts +27 -0
- package/dist/node-default-transports.js +35 -0
- package/dist/node-default-transports.js.map +1 -0
- package/dist/node-transports.d.ts +30 -0
- package/dist/node-transports.js +40 -0
- package/dist/node-transports.js.map +1 -0
- package/dist/owner-anchor-sync.d.ts +22 -0
- package/dist/owner-anchor-sync.js +143 -0
- package/dist/owner-anchor-sync.js.map +1 -0
- package/dist/peer-authorization.d.ts +113 -18
- package/dist/peer-authorization.js +225 -29
- package/dist/peer-authorization.js.map +1 -1
- package/dist/peer-dial.d.ts +143 -27
- package/dist/peer-dial.js +276 -31
- package/dist/peer-dial.js.map +1 -1
- package/dist/peer-join-backfill.d.ts +26 -2
- package/dist/peer-join-backfill.js +60 -12
- package/dist/peer-join-backfill.js.map +1 -1
- package/dist/peer-record.d.ts +17 -52
- package/dist/peer-record.js +20 -58
- package/dist/peer-record.js.map +1 -1
- package/dist/pending-join-runner.d.ts +66 -58
- package/dist/pending-join-runner.js +136 -145
- package/dist/pending-join-runner.js.map +1 -1
- package/dist/primary-lan-address.d.ts +8 -0
- package/dist/primary-lan-address.js +46 -0
- package/dist/primary-lan-address.js.map +1 -0
- package/dist/provider/client.d.ts +131 -0
- package/dist/provider/client.js +226 -0
- package/dist/provider/client.js.map +1 -0
- package/dist/provider/descriptor.d.ts +41 -0
- package/dist/provider/descriptor.js +103 -0
- package/dist/provider/descriptor.js.map +1 -0
- package/dist/provider/index.d.ts +9 -0
- package/dist/provider/index.js +10 -0
- package/dist/provider/index.js.map +1 -0
- package/dist/provider/oauth.d.ts +125 -0
- package/dist/provider/oauth.js +199 -0
- package/dist/provider/oauth.js.map +1 -0
- package/dist/provider/rent-node.d.ts +101 -0
- package/dist/provider/rent-node.js +220 -0
- package/dist/provider/rent-node.js.map +1 -0
- package/dist/push-fanout.d.ts +8 -2
- package/dist/push-fanout.js +8 -2
- package/dist/push-fanout.js.map +1 -1
- package/dist/relay-addrs.d.ts +9 -4
- package/dist/relay-addrs.js +9 -4
- package/dist/relay-addrs.js.map +1 -1
- package/dist/relay-reservation.d.ts +51 -16
- package/dist/relay-reservation.js +107 -24
- package/dist/relay-reservation.js.map +1 -1
- package/dist/seed-bootstrap.d.ts +165 -123
- package/dist/seed-bootstrap.js +313 -275
- package/dist/seed-bootstrap.js.map +1 -1
- package/dist/seed-trust-policy.d.ts +98 -37
- package/dist/seed-trust-policy.js +188 -2
- package/dist/seed-trust-policy.js.map +1 -1
- package/dist/strand-addr-protocol.d.ts +24 -26
- package/dist/strand-addr-protocol.js +19 -26
- package/dist/strand-addr-protocol.js.map +1 -1
- package/dist/strand-commit-durability.d.ts +54 -0
- package/dist/strand-commit-durability.js +74 -0
- package/dist/strand-commit-durability.js.map +1 -0
- package/dist/strand-database.d.ts +23 -8
- package/dist/strand-database.js +41 -13
- package/dist/strand-database.js.map +1 -1
- package/dist/strand-first-sync-gate.d.ts +7 -1
- package/dist/strand-first-sync-gate.js +7 -1
- package/dist/strand-first-sync-gate.js.map +1 -1
- package/dist/strand-formation-protocol.js +5 -2
- package/dist/strand-formation-protocol.js.map +1 -1
- package/dist/strand-fret-addrs.d.ts +19 -1
- package/dist/strand-fret-addrs.js +27 -9
- package/dist/strand-fret-addrs.js.map +1 -1
- package/dist/strand-instance-manager.d.ts +81 -19
- package/dist/strand-instance-manager.js +216 -105
- package/dist/strand-instance-manager.js.map +1 -1
- package/dist/strand-move.d.ts +124 -0
- package/dist/strand-move.js +438 -0
- package/dist/strand-move.js.map +1 -0
- package/dist/strand-network-config.js +7 -6
- package/dist/strand-network-config.js.map +1 -1
- package/dist/strand-peer-redial.d.ts +113 -0
- package/dist/strand-peer-redial.js +236 -0
- package/dist/strand-peer-redial.js.map +1 -0
- package/dist/strand-revocation-enforcer.d.ts +11 -11
- package/dist/strand-revocation-enforcer.js +11 -11
- package/dist/strand-wake-protocol.d.ts +13 -16
- package/dist/strand-wake-protocol.js +23 -27
- package/dist/strand-wake-protocol.js.map +1 -1
- package/dist/trusted-owner-store.d.ts +35 -5
- package/dist/trusted-owner-store.js +50 -8
- package/dist/trusted-owner-store.js.map +1 -1
- package/dist/types.d.ts +512 -89
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -1
- package/package.json +19 -10
- package/src/cadre-invite-protocol.ts +1052 -0
- package/src/cadre-join-request.ts +167 -0
- package/src/cadre-node.ts +1703 -386
- package/src/claim-proof.ts +147 -0
- package/src/control-authorization.ts +203 -117
- package/src/control-cohort.ts +1 -1
- package/src/control-database.ts +4663 -3453
- package/src/control-protocol-guard.ts +348 -0
- package/src/control-schema.ts +828 -1078
- package/src/control-stream.ts +26 -7
- package/src/delegate-admission.ts +1 -1
- package/src/device-token.ts +14 -10
- package/src/ed25519-key.ts +47 -10
- package/src/fetch-impl.ts +23 -0
- package/src/file-durable-slot.ts +64 -63
- package/src/file-safe-name.ts +32 -0
- package/src/formation-approval.ts +604 -610
- package/src/fs-atomic.ts +92 -117
- package/src/index.ts +789 -648
- package/src/invitation-bootstrap.ts +91 -13
- package/src/joined-strand-store.ts +508 -498
- package/src/key-store-file.ts +142 -141
- package/src/link-budget.ts +25 -36
- package/src/machine-removal.ts +216 -0
- package/src/membership-connection-gater.ts +259 -191
- package/src/node-claim-payload.ts +259 -0
- package/src/node-default-transports.ts +38 -0
- package/src/node-transports.ts +49 -0
- package/src/owner-anchor-sync.ts +171 -0
- package/src/peer-authorization.ts +258 -29
- package/src/peer-dial.ts +604 -315
- package/src/peer-join-backfill.ts +62 -11
- package/src/peer-record.ts +159 -197
- package/src/pending-join-runner.ts +729 -735
- package/src/primary-lan-address.ts +47 -0
- package/src/provider/client.ts +326 -0
- package/src/provider/descriptor.ts +129 -0
- package/src/provider/index.ts +59 -0
- package/src/provider/oauth.ts +285 -0
- package/src/provider/rent-node.ts +275 -0
- package/src/push-fanout.ts +8 -2
- package/src/relay-addrs.ts +9 -4
- package/src/relay-reservation.ts +1211 -1121
- package/src/seed-bootstrap.ts +1502 -1448
- package/src/seed-trust-policy.ts +353 -140
- package/src/strand-addr-protocol.ts +26 -35
- package/src/strand-commit-durability.ts +116 -0
- package/src/strand-database.ts +46 -14
- package/src/strand-first-sync-gate.ts +7 -1
- package/src/strand-formation-protocol.ts +1039 -1036
- package/src/strand-fret-addrs.ts +179 -145
- package/src/strand-instance-manager.ts +2026 -1883
- package/src/strand-move.ts +585 -0
- package/src/strand-network-config.ts +7 -6
- package/src/strand-peer-redial.ts +307 -0
- package/src/strand-revocation-enforcer.ts +11 -11
- package/src/strand-wake-protocol.ts +23 -30
- package/src/trusted-owner-store.ts +242 -171
- package/src/types.ts +2687 -2242
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { SeedRefusalCode } from './types.js';
|
|
2
|
+
/** Length of a claim secret: 256 bits, so guessing one is infeasible. */
|
|
3
|
+
export declare const CLAIM_SECRET_BYTES = 32;
|
|
4
|
+
/**
|
|
5
|
+
* Thrown by `CadreNode.claimNode` when the node answered the claim seed with a refusal.
|
|
6
|
+
* Distinct from `PeerUnreachableError` (no connection to the node formed) and from a
|
|
7
|
+
* failure after the node was reached (thrown by `deliverSeed` as is): here the node was
|
|
8
|
+
* reached and said no. `code` is the node's machine-readable cause
|
|
9
|
+
* when its policy supplied one (`already-claimed`, `claim-proof-invalid`, ...), so a
|
|
10
|
+
* phone can tell "someone else owns it" from "wrong secret" without parsing `reason`.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ClaimRefusedError extends Error {
|
|
13
|
+
readonly nodePeerId: string;
|
|
14
|
+
readonly reason: string;
|
|
15
|
+
readonly code?: SeedRefusalCode | undefined;
|
|
16
|
+
constructor(nodePeerId: string, reason: string, code?: SeedRefusalCode | undefined);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Decode a claim secret from the base64url text the host shows and the phone scans.
|
|
20
|
+
*
|
|
21
|
+
* Refuses anything that is not base64url of exactly {@link CLAIM_SECRET_BYTES} bytes,
|
|
22
|
+
* naming the problem. The rejected value is never echoed: unlike a public key, a
|
|
23
|
+
* mistyped secret may still be a secret.
|
|
24
|
+
*
|
|
25
|
+
* @returns The 32 secret bytes.
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseClaimSecret(text: string): Uint8Array;
|
|
28
|
+
/**
|
|
29
|
+
* Compute the claim proof the owner side sends beside its seed.
|
|
30
|
+
*
|
|
31
|
+
* @param secret - The parsed 32-byte claim secret ({@link parseClaimSecret}).
|
|
32
|
+
* @param nodePeerId - The peer id of the node being claimed.
|
|
33
|
+
* @param signerKey - The owner key that signed the seed (base64url).
|
|
34
|
+
* @param seedDigest - The seed's signature digest (`seedDigest()` in `seed-bootstrap.ts`).
|
|
35
|
+
* @returns The proof, base64url.
|
|
36
|
+
*/
|
|
37
|
+
export declare function claimProof(secret: Uint8Array, nodePeerId: string, signerKey: string, seedDigest: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* Check a presented proof against the receiver's own view of the three bound fields.
|
|
40
|
+
*
|
|
41
|
+
* Recomputes the tag and compares in constant time. A proof that does not decode as
|
|
42
|
+
* base64url is simply invalid. `nodePeerId` must be the RECEIVER's own peer id, never
|
|
43
|
+
* one the sender supplied; that is what makes a captured proof useless elsewhere.
|
|
44
|
+
*/
|
|
45
|
+
export declare function verifyClaimProof(secret: Uint8Array, nodePeerId: string, signerKey: string, seedDigest: string, proof: string): boolean;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claim proof: how the first seed delivered to a brand-new node proves that its sender
|
|
3
|
+
* holds the node's one-time claim secret.
|
|
4
|
+
*
|
|
5
|
+
* A node that belongs to nobody yet (a cadre-host child before its owner scans the QR
|
|
6
|
+
* code) has an empty trusted-owner anchor, so every seed trust policy refuses its first
|
|
7
|
+
* seed. The claim secret is the out-of-band channel that breaks the deadlock: the host
|
|
8
|
+
* mints 32 random bytes, shows them beside the node's addresses, and the owner's phone
|
|
9
|
+
* proves possession by sending, next to the seed, an HMAC keyed by those bytes.
|
|
10
|
+
*
|
|
11
|
+
* The proof is `base64url(HMAC-SHA256(secret, utf8(canonicalJson(payload))))` where
|
|
12
|
+
* `payload` is `{ purpose: 'sereus-node-claim', v: 1, nodePeerId, signerKey, seedDigest }`:
|
|
13
|
+
*
|
|
14
|
+
* - `nodePeerId` binds the proof to one node, so a captured proof cannot claim another
|
|
15
|
+
* node minted with the same secret;
|
|
16
|
+
* - `signerKey` binds it to one owner, so it cannot anchor a different key;
|
|
17
|
+
* - `seedDigest` (the same digest the seed signature covers, `seedDigest()` in
|
|
18
|
+
* `seed-bootstrap.ts`) binds it to one seed, so it cannot be reattached to another.
|
|
19
|
+
*
|
|
20
|
+
* A passive observer of one delivery therefore learns a proof that is useless anywhere
|
|
21
|
+
* else, and useless on this node once it is claimed. A keyed MAC is the standard way to
|
|
22
|
+
* prove possession of a secret without revealing it; the crypto plugin's framed
|
|
23
|
+
* `digest([...])` helper is not specified as one, so the secret is never fed to it.
|
|
24
|
+
*
|
|
25
|
+
* Verified by `claimSecretTrustPolicy` (`seed-trust-policy.ts`). Imports only
|
|
26
|
+
* `@noble/hashes`, `uint8arrays` and `canonical-json.ts`: this module loads on React
|
|
27
|
+
* Native and in the browser as well as Node.
|
|
28
|
+
*/
|
|
29
|
+
import debug from 'debug';
|
|
30
|
+
import { hmac } from '@noble/hashes/hmac.js';
|
|
31
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
32
|
+
import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays';
|
|
33
|
+
import { canonicalJson } from './canonical-json.js';
|
|
34
|
+
const log = debug('sereus:cadre:claim-proof');
|
|
35
|
+
/** Length of a claim secret: 256 bits, so guessing one is infeasible. */
|
|
36
|
+
export const CLAIM_SECRET_BYTES = 32;
|
|
37
|
+
/**
|
|
38
|
+
* Thrown by `CadreNode.claimNode` when the node answered the claim seed with a refusal.
|
|
39
|
+
* Distinct from `PeerUnreachableError` (no connection to the node formed) and from a
|
|
40
|
+
* failure after the node was reached (thrown by `deliverSeed` as is): here the node was
|
|
41
|
+
* reached and said no. `code` is the node's machine-readable cause
|
|
42
|
+
* when its policy supplied one (`already-claimed`, `claim-proof-invalid`, ...), so a
|
|
43
|
+
* phone can tell "someone else owns it" from "wrong secret" without parsing `reason`.
|
|
44
|
+
*/
|
|
45
|
+
export class ClaimRefusedError extends Error {
|
|
46
|
+
constructor(nodePeerId, reason, code) {
|
|
47
|
+
super(`Node ${nodePeerId} refused the claim${code ? ` (${code})` : ''}: ${reason}`);
|
|
48
|
+
this.nodePeerId = nodePeerId;
|
|
49
|
+
this.reason = reason;
|
|
50
|
+
this.code = code;
|
|
51
|
+
this.name = 'ClaimRefusedError';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Decode a claim secret from the base64url text the host shows and the phone scans.
|
|
56
|
+
*
|
|
57
|
+
* Refuses anything that is not base64url of exactly {@link CLAIM_SECRET_BYTES} bytes,
|
|
58
|
+
* naming the problem. The rejected value is never echoed: unlike a public key, a
|
|
59
|
+
* mistyped secret may still be a secret.
|
|
60
|
+
*
|
|
61
|
+
* @returns The 32 secret bytes.
|
|
62
|
+
*/
|
|
63
|
+
export function parseClaimSecret(text) {
|
|
64
|
+
const trimmed = text.trim();
|
|
65
|
+
if (trimmed.length === 0) {
|
|
66
|
+
throw new Error('A claim secret is required (received an empty or whitespace-only value)');
|
|
67
|
+
}
|
|
68
|
+
let decoded;
|
|
69
|
+
try {
|
|
70
|
+
decoded = uint8ArrayFromString(trimmed, 'base64url');
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
throw new Error('A claim secret must be base64url text (the value could not be decoded as base64url)', { cause: error });
|
|
74
|
+
}
|
|
75
|
+
if (decoded.length !== CLAIM_SECRET_BYTES) {
|
|
76
|
+
throw new Error(`A claim secret must decode to exactly ${CLAIM_SECRET_BYTES} bytes (the value decoded to ${decoded.length})`);
|
|
77
|
+
}
|
|
78
|
+
return decoded;
|
|
79
|
+
}
|
|
80
|
+
/** The HMAC tag bytes over the canonical claim payload (see the module doc). */
|
|
81
|
+
function claimProofBytes(secret, nodePeerId, signerKey, seedDigest) {
|
|
82
|
+
const payload = canonicalJson({ purpose: 'sereus-node-claim', v: 1, nodePeerId, signerKey, seedDigest });
|
|
83
|
+
return hmac(sha256, secret, new TextEncoder().encode(payload));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Compute the claim proof the owner side sends beside its seed.
|
|
87
|
+
*
|
|
88
|
+
* @param secret - The parsed 32-byte claim secret ({@link parseClaimSecret}).
|
|
89
|
+
* @param nodePeerId - The peer id of the node being claimed.
|
|
90
|
+
* @param signerKey - The owner key that signed the seed (base64url).
|
|
91
|
+
* @param seedDigest - The seed's signature digest (`seedDigest()` in `seed-bootstrap.ts`).
|
|
92
|
+
* @returns The proof, base64url.
|
|
93
|
+
*/
|
|
94
|
+
export function claimProof(secret, nodePeerId, signerKey, seedDigest) {
|
|
95
|
+
return uint8ArrayToString(claimProofBytes(secret, nodePeerId, signerKey, seedDigest), 'base64url');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Check a presented proof against the receiver's own view of the three bound fields.
|
|
99
|
+
*
|
|
100
|
+
* Recomputes the tag and compares in constant time. A proof that does not decode as
|
|
101
|
+
* base64url is simply invalid. `nodePeerId` must be the RECEIVER's own peer id, never
|
|
102
|
+
* one the sender supplied; that is what makes a captured proof useless elsewhere.
|
|
103
|
+
*/
|
|
104
|
+
export function verifyClaimProof(secret, nodePeerId, signerKey, seedDigest, proof) {
|
|
105
|
+
let presented;
|
|
106
|
+
try {
|
|
107
|
+
presented = uint8ArrayFromString(proof, 'base64url');
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
log('claim proof is not base64url: %o', error);
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
return constantTimeEqual(presented, claimProofBytes(secret, nodePeerId, signerKey, seedDigest));
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Byte equality whose running time does not depend on WHERE the arrays differ, so a
|
|
117
|
+
* remote cannot learn a valid proof prefix from response timing. The length check
|
|
118
|
+
* short-circuits, which leaks nothing: a valid proof's length is public. A plain loop
|
|
119
|
+
* rather than `node:crypto`'s `timingSafeEqual` because this module must load on React
|
|
120
|
+
* Native and in the browser.
|
|
121
|
+
*/
|
|
122
|
+
function constantTimeEqual(a, b) {
|
|
123
|
+
if (a.length !== b.length) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
let diff = 0;
|
|
127
|
+
for (let i = 0; i < a.length; i++) {
|
|
128
|
+
diff |= a[i] ^ b[i];
|
|
129
|
+
}
|
|
130
|
+
return diff === 0;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=claim-proof.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim-proof.js","sourceRoot":"","sources":["../src/claim-proof.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,14 +6,24 @@
|
|
|
6
6
|
* byte layout cannot drift between them or away from the SQL constraints in
|
|
7
7
|
* `schemas/control.qsql`.
|
|
8
8
|
*
|
|
9
|
-
* Every vector leads with two fixed literals:
|
|
9
|
+
* Every vector leads with two fixed literals and the party id:
|
|
10
10
|
*
|
|
11
|
-
* digest(<domain>, <action>, <row field 1>, ..., <row field n>)
|
|
11
|
+
* digest(<domain>, <action>, <party id>, <row field 1>, ..., <row field n>)
|
|
12
12
|
*
|
|
13
|
-
* so a signature verifies ONLY against the one rule
|
|
14
|
-
* the tags, several rules built byte-identical tuples (e.g.
|
|
15
|
-
* insert and `OwnerKey` insert both signed `digest(Key, StampId)`),
|
|
16
|
-
* approval for a narrow grant doubled as an approval for full ownership.
|
|
13
|
+
* so a signature verifies ONLY against the one rule, in the one party, it was
|
|
14
|
+
* minted for. Without the tags, several rules built byte-identical tuples (e.g.
|
|
15
|
+
* `ValidationKey` insert and `OwnerKey` insert both signed `digest(Key, StampId)`),
|
|
16
|
+
* so an approval for a narrow grant doubled as an approval for full ownership.
|
|
17
|
+
* Without the party, two parties sharing an owner key (one node key owning two
|
|
18
|
+
* cadres, a hardware owner key) would accept each other's approvals. The SQL side
|
|
19
|
+
* reads the party from the node-local `party_id()` function `ControlDatabase`
|
|
20
|
+
* registers (never from a context value or a replicated table), and every
|
|
21
|
+
* TypeScript signer and verifier passes the party it is configured for.
|
|
22
|
+
*
|
|
23
|
+
* Two digests carry NO party ({@link UnboundControlDomain}): the `FormationUsage`
|
|
24
|
+
* `'consent'` and `'vouch'` digests, whose signers do not know the party (see the
|
|
25
|
+
* schema's `FormationUsage.Authorized` comment), and the offline `'Cadre.Enrollment'`
|
|
26
|
+
* vouch, which no table checks.
|
|
17
27
|
*
|
|
18
28
|
* This module deliberately has no Quereus / Optimystic / libp2p imports so the
|
|
19
29
|
* lightweight verifiers (`peer-authorization.ts`, consumed by the offline
|
|
@@ -33,7 +43,7 @@
|
|
|
33
43
|
* CHECK the `'reissue'`-tagged digest `ControlDatabase.reissueRevocations`
|
|
34
44
|
* signs — and `countRows` counts it.
|
|
35
45
|
*/
|
|
36
|
-
export declare const CONTROL_TABLES: readonly ["OwnerKey", "ValidationKey", "Strand", "StrandPartyKey", "JoinedStrand", "
|
|
46
|
+
export declare const CONTROL_TABLES: readonly ["OwnerKey", "ValidationKey", "Strand", "StrandPartyKey", "JoinedStrand", "JoinRequest", "JoinSuccess", "JoinFailure", "CadrePeer", "DeviceToken", "FormationInvite", "FormationUsage", "CadreInvite", "CadreInviteUsage", "Revocation"];
|
|
37
47
|
/**
|
|
38
48
|
* Name of a CadreControl table. Doubles as the table half of a
|
|
39
49
|
* {@link ControlDomain} tag.
|
|
@@ -47,11 +57,17 @@ export type ControlTable = typeof CONTROL_TABLES[number];
|
|
|
47
57
|
* {@link ControlTable} rather than a fresh literal list, so a renamed table is a
|
|
48
58
|
* compile error here instead of a silently dead branch.
|
|
49
59
|
*
|
|
60
|
+
* `CadreInvite` is the one member whose rows are never deleted: its tombstone is a
|
|
61
|
+
* withdrawal over a row that stays (`NotRevoked` refuses re-seating the withdrawn
|
|
62
|
+
* row; there is no `RevocationRecorded`, since nothing is ever removed), so it is
|
|
63
|
+
* revocable without being removable — `control-database.ts`'s `RemovableTable`
|
|
64
|
+
* excludes it.
|
|
65
|
+
*
|
|
50
66
|
* Lives in this import-free module rather than beside its main consumer
|
|
51
67
|
* (`control-database.ts`) so the lightweight signers — `peer-authorization.ts`'s
|
|
52
68
|
* `revocationDigest` — can type against it without pulling in the runtime.
|
|
53
69
|
*/
|
|
54
|
-
export type RevocableTable = Extract<ControlTable, 'OwnerKey' | 'CadrePeer' | 'ValidationKey' | 'Strand' | 'StrandPartyKey' | 'JoinedStrand' | '
|
|
70
|
+
export type RevocableTable = Extract<ControlTable, 'OwnerKey' | 'CadrePeer' | 'ValidationKey' | 'Strand' | 'StrandPartyKey' | 'JoinedStrand' | 'JoinRequest' | 'DeviceToken' | 'CadreInvite'>;
|
|
55
71
|
/**
|
|
56
72
|
* What a signature authorizes, scoped to one table rule — or, for
|
|
57
73
|
* `'Cadre.Enrollment'`, the offline peer vouch that `cadre enroll register`
|
|
@@ -59,6 +75,15 @@ export type RevocableTable = Extract<ControlTable, 'OwnerKey' | 'CadrePeer' | 'V
|
|
|
59
75
|
* from every table rule).
|
|
60
76
|
*/
|
|
61
77
|
export type ControlDomain = `CadreControl.${ControlTable}` | 'Cadre.Enrollment';
|
|
78
|
+
/**
|
|
79
|
+
* The domains whose digests bind no party id — the only two
|
|
80
|
+
* {@link unboundAuthorizationFields} accepts. `FormationUsage`: neither signer knows
|
|
81
|
+
* the party, and the invitation token scopes the digest instead (the reason is at the
|
|
82
|
+
* schema's `FormationUsage.Authorized` comment). `Cadre.Enrollment`: no table checks it.
|
|
83
|
+
*/
|
|
84
|
+
export type UnboundControlDomain = 'CadreControl.FormationUsage' | 'Cadre.Enrollment';
|
|
85
|
+
/** Every domain whose digests bind the party id — the only ones {@link controlAuthorizationFields} accepts. */
|
|
86
|
+
export type BoundControlDomain = Exclude<ControlDomain, UnboundControlDomain>;
|
|
62
87
|
/**
|
|
63
88
|
* The action half of the tag:
|
|
64
89
|
* - `'add'` / `'remove'` — insert / delete of the named row.
|
|
@@ -72,22 +97,58 @@ export type ControlDomain = `CadreControl.${ControlTable}` | 'Cadre.Enrollment';
|
|
|
72
97
|
* - `'publish'` — a peer self-signs its OWN record (the `CadrePeer` /
|
|
73
98
|
* `DeviceToken` self-update branches), with its own key rather than an
|
|
74
99
|
* owner key.
|
|
75
|
-
* - `'consent'` — a peer self-signs its OWN `FormationUsage`
|
|
76
|
-
* joiner proving it agreed to join), with
|
|
77
|
-
* approver's `'vouch'` over the same table so
|
|
78
|
-
* never interchangeable.
|
|
100
|
+
* - `'consent'` — a peer self-signs its OWN `FormationUsage` or
|
|
101
|
+
* `CadreInviteUsage` redemption (the joiner proving it agreed to join), with
|
|
102
|
+
* its own key. Distinct from the approver's `'vouch'` over the same table so
|
|
103
|
+
* the two stored signatures are never interchangeable.
|
|
104
|
+
* - `'redeem'` — the holder of a `CadreInvite`'s private key proves possession
|
|
105
|
+
* on a `CadreInviteUsage` row. Distinct from the device's `'consent'` over the
|
|
106
|
+
* same fields: the two signatures are by different keys and neither may stand
|
|
107
|
+
* in for the other.
|
|
79
108
|
* - `'reissue'` — an owner re-writes an existing `Revocation` tombstone,
|
|
80
109
|
* bumping its `ReissuedAt` counter so a tombstone committed while the node
|
|
81
110
|
* was alone can be re-broadcast. Distinct from `'remove'` so a tombstone
|
|
82
111
|
* append approval can never be replayed as a re-issue and vice versa.
|
|
83
112
|
*/
|
|
84
|
-
export type ControlAction = 'add' | 'remove' | 'vouch' | 'publish' | 'consent' | 'reissue';
|
|
113
|
+
export type ControlAction = 'add' | 'remove' | 'vouch' | 'publish' | 'consent' | 'redeem' | 'reissue';
|
|
114
|
+
/**
|
|
115
|
+
* The `CadreInvite` columns its `'add'` signature binds, in the schema's order and
|
|
116
|
+
* with the row's stored forms: `expiresAt` is the engine-canonical `datetime` string
|
|
117
|
+
* (`canonicalDatetime`), never epoch ms, because the SQL side digests
|
|
118
|
+
* `cast(new.ExpiresAt as text)` after coercion. Structurally satisfied by a
|
|
119
|
+
* `CadreInviteRow` (`types.ts`), which adds the issuer pair the signature does not cover.
|
|
120
|
+
*/
|
|
121
|
+
export interface CadreInviteSignedFields {
|
|
122
|
+
key: string;
|
|
123
|
+
peerId: string | null;
|
|
124
|
+
grantsOwner: boolean;
|
|
125
|
+
expiresAt: string | null;
|
|
126
|
+
totalUses: number | null;
|
|
127
|
+
stampId: string;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The row-field half of a `CadreInvite` `'add'` digest, shared by the signer
|
|
131
|
+
* (`control-database.ts`'s `cadreInviteAddMessage`, raw bytes) and the verifier
|
|
132
|
+
* (`peer-authorization.ts`'s `cadreInviteAddDigest`, base64url) so the two cannot
|
|
133
|
+
* drift. SQL mirror, in `CadreInvite.AuthorizedInsert`:
|
|
134
|
+
* `new.Key, coalesce(new.PeerId, ''), cast(new.GrantsOwner as text),
|
|
135
|
+
* coalesce(cast(new.ExpiresAt as text), ''), coalesce(cast(new.TotalUses as text), ''), new.StampId`.
|
|
136
|
+
*/
|
|
137
|
+
export declare function cadreInviteRowFields(row: CadreInviteSignedFields): string[];
|
|
138
|
+
/**
|
|
139
|
+
* The full ordered field vector a party-bound control-plane signature covers. Digest
|
|
140
|
+
* this with the crypto plugin's injective multi-field encoding (every field TEXT);
|
|
141
|
+
* the SQL mirror passes the same literals as leading `digest(...)` arguments and
|
|
142
|
+
* reads the party from its node-local `party_id()`:
|
|
143
|
+
*
|
|
144
|
+
* TS: digest(controlAuthorizationFields('CadreControl.X', 'add', partyId, [a, b]), 'sha256', ...)
|
|
145
|
+
* SQL: digest('CadreControl.X', 'add', party_id(), new.A, new.B)
|
|
146
|
+
*/
|
|
147
|
+
export declare function controlAuthorizationFields(domain: BoundControlDomain, action: ControlAction, partyId: string, rowFields: string[]): string[];
|
|
85
148
|
/**
|
|
86
|
-
* The
|
|
87
|
-
* with the crypto plugin's injective multi-field encoding (every field TEXT);
|
|
88
|
-
* the SQL mirror passes the same literals as leading `digest(...)` arguments:
|
|
149
|
+
* The field vector of the two party-free digests ({@link UnboundControlDomain}):
|
|
89
150
|
*
|
|
90
|
-
* TS: digest(
|
|
91
|
-
* SQL: digest('CadreControl.
|
|
151
|
+
* TS: digest(unboundAuthorizationFields('CadreControl.FormationUsage', 'consent', [a, b]), 'sha256', ...)
|
|
152
|
+
* SQL: digest('CadreControl.FormationUsage', 'consent', new.A, new.B)
|
|
92
153
|
*/
|
|
93
|
-
export declare function
|
|
154
|
+
export declare function unboundAuthorizationFields(domain: UnboundControlDomain, action: ControlAction, rowFields: string[]): string[];
|
|
@@ -6,14 +6,24 @@
|
|
|
6
6
|
* byte layout cannot drift between them or away from the SQL constraints in
|
|
7
7
|
* `schemas/control.qsql`.
|
|
8
8
|
*
|
|
9
|
-
* Every vector leads with two fixed literals:
|
|
9
|
+
* Every vector leads with two fixed literals and the party id:
|
|
10
10
|
*
|
|
11
|
-
* digest(<domain>, <action>, <row field 1>, ..., <row field n>)
|
|
11
|
+
* digest(<domain>, <action>, <party id>, <row field 1>, ..., <row field n>)
|
|
12
12
|
*
|
|
13
|
-
* so a signature verifies ONLY against the one rule
|
|
14
|
-
* the tags, several rules built byte-identical tuples (e.g.
|
|
15
|
-
* insert and `OwnerKey` insert both signed `digest(Key, StampId)`),
|
|
16
|
-
* approval for a narrow grant doubled as an approval for full ownership.
|
|
13
|
+
* so a signature verifies ONLY against the one rule, in the one party, it was
|
|
14
|
+
* minted for. Without the tags, several rules built byte-identical tuples (e.g.
|
|
15
|
+
* `ValidationKey` insert and `OwnerKey` insert both signed `digest(Key, StampId)`),
|
|
16
|
+
* so an approval for a narrow grant doubled as an approval for full ownership.
|
|
17
|
+
* Without the party, two parties sharing an owner key (one node key owning two
|
|
18
|
+
* cadres, a hardware owner key) would accept each other's approvals. The SQL side
|
|
19
|
+
* reads the party from the node-local `party_id()` function `ControlDatabase`
|
|
20
|
+
* registers (never from a context value or a replicated table), and every
|
|
21
|
+
* TypeScript signer and verifier passes the party it is configured for.
|
|
22
|
+
*
|
|
23
|
+
* Two digests carry NO party ({@link UnboundControlDomain}): the `FormationUsage`
|
|
24
|
+
* `'consent'` and `'vouch'` digests, whose signers do not know the party (see the
|
|
25
|
+
* schema's `FormationUsage.Authorized` comment), and the offline `'Cadre.Enrollment'`
|
|
26
|
+
* vouch, which no table checks.
|
|
17
27
|
*
|
|
18
28
|
* This module deliberately has no Quereus / Optimystic / libp2p imports so the
|
|
19
29
|
* lightweight verifiers (`peer-authorization.ts`, consumed by the offline
|
|
@@ -39,22 +49,54 @@ export const CONTROL_TABLES = [
|
|
|
39
49
|
'Strand',
|
|
40
50
|
'StrandPartyKey',
|
|
41
51
|
'JoinedStrand',
|
|
42
|
-
'
|
|
52
|
+
'JoinRequest',
|
|
53
|
+
'JoinSuccess',
|
|
54
|
+
'JoinFailure',
|
|
43
55
|
'CadrePeer',
|
|
44
56
|
'DeviceToken',
|
|
45
57
|
'FormationInvite',
|
|
46
58
|
'FormationUsage',
|
|
59
|
+
'CadreInvite',
|
|
60
|
+
'CadreInviteUsage',
|
|
47
61
|
'Revocation',
|
|
48
62
|
];
|
|
49
63
|
/**
|
|
50
|
-
* The
|
|
51
|
-
*
|
|
52
|
-
*
|
|
64
|
+
* The row-field half of a `CadreInvite` `'add'` digest, shared by the signer
|
|
65
|
+
* (`control-database.ts`'s `cadreInviteAddMessage`, raw bytes) and the verifier
|
|
66
|
+
* (`peer-authorization.ts`'s `cadreInviteAddDigest`, base64url) so the two cannot
|
|
67
|
+
* drift. SQL mirror, in `CadreInvite.AuthorizedInsert`:
|
|
68
|
+
* `new.Key, coalesce(new.PeerId, ''), cast(new.GrantsOwner as text),
|
|
69
|
+
* coalesce(cast(new.ExpiresAt as text), ''), coalesce(cast(new.TotalUses as text), ''), new.StampId`.
|
|
70
|
+
*/
|
|
71
|
+
export function cadreInviteRowFields(row) {
|
|
72
|
+
return [
|
|
73
|
+
row.key,
|
|
74
|
+
row.peerId ?? '',
|
|
75
|
+
row.grantsOwner ? '1' : '0',
|
|
76
|
+
row.expiresAt ?? '',
|
|
77
|
+
row.totalUses === null ? '' : String(row.totalUses),
|
|
78
|
+
row.stampId,
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The full ordered field vector a party-bound control-plane signature covers. Digest
|
|
83
|
+
* this with the crypto plugin's injective multi-field encoding (every field TEXT);
|
|
84
|
+
* the SQL mirror passes the same literals as leading `digest(...)` arguments and
|
|
85
|
+
* reads the party from its node-local `party_id()`:
|
|
86
|
+
*
|
|
87
|
+
* TS: digest(controlAuthorizationFields('CadreControl.X', 'add', partyId, [a, b]), 'sha256', ...)
|
|
88
|
+
* SQL: digest('CadreControl.X', 'add', party_id(), new.A, new.B)
|
|
89
|
+
*/
|
|
90
|
+
export function controlAuthorizationFields(domain, action, partyId, rowFields) {
|
|
91
|
+
return [domain, action, partyId, ...rowFields];
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The field vector of the two party-free digests ({@link UnboundControlDomain}):
|
|
53
95
|
*
|
|
54
|
-
* TS: digest(
|
|
55
|
-
* SQL: digest('CadreControl.
|
|
96
|
+
* TS: digest(unboundAuthorizationFields('CadreControl.FormationUsage', 'consent', [a, b]), 'sha256', ...)
|
|
97
|
+
* SQL: digest('CadreControl.FormationUsage', 'consent', new.A, new.B)
|
|
56
98
|
*/
|
|
57
|
-
export function
|
|
99
|
+
export function unboundAuthorizationFields(domain, action, rowFields) {
|
|
58
100
|
return [domain, action, ...rowFields];
|
|
59
101
|
}
|
|
60
102
|
//# sourceMappingURL=control-authorization.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-authorization.js","sourceRoot":"","sources":["../src/control-authorization.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"control-authorization.js","sourceRoot":"","sources":["../src/control-authorization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,UAAU;IACV,eAAe;IACf,QAAQ;IACR,gBAAgB;IAChB,cAAc;IACd,aAAa;IACb,aAAa;IACb,aAAa;IACb,WAAW;IACX,aAAa;IACb,iBAAiB;IACjB,gBAAgB;IAChB,aAAa;IACb,kBAAkB;IAClB,YAAY;CACJ,CAAC;AA2FX;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAA4B;IAC/D,OAAO;QACL,GAAG,CAAC,GAAG;QACP,GAAG,CAAC,MAAM,IAAI,EAAE;QAChB,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;QAC3B,GAAG,CAAC,SAAS,IAAI,EAAE;QACnB,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;QACnD,GAAG,CAAC,OAAO;KACZ,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAA0B,EAC1B,MAAqB,EACrB,OAAe,EACf,SAAmB;IAEnB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAA4B,EAC5B,MAAqB,EACrB,SAAmB;IAEnB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;AACxC,CAAC"}
|
package/dist/control-cohort.js
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* correct, cheap, and matches what the convergence tests do by hand; for a large
|
|
21
21
|
* party it bounds out-degree to `backbone + targetDegree`.
|
|
22
22
|
*/
|
|
23
|
-
import { ed25519PublicKeyB64FromPeerId } from './
|
|
23
|
+
import { ed25519PublicKeyB64FromPeerId } from './ed25519-key.js';
|
|
24
24
|
/**
|
|
25
25
|
* Default recurring cadence for {@link CadreNode.reconcileControlCohort} (ms).
|
|
26
26
|
* In the same spirit as the 5s strand-watch poll but lighter, since a control
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-cohort.js","sourceRoot":"","sources":["../src/control-cohort.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,6BAA6B,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"control-cohort.js","sourceRoot":"","sources":["../src/control-cohort.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAGjE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,KAAM,CAAC;AAE1D;;;;GAIG;AACH,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC,CAAC;AAkCtD,mFAAmF;AACnF,SAAS,QAAQ,CAAC,CAAgB,EAAE,CAAgB;IAClD,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC,CAAC;IACnC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QAAE,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAyB,EACzB,SAA8B,EAC9B,YAAoB;IAEpB,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,IAAI,GAAoB,EAAE,CAAC;IAEjC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,6BAA6B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1D,IAAI,MAAM,KAAK,IAAI,IAAI,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEpB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEhC,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC;QAC7B,cAAc,EAAE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM;KAC1C,CAAC;AACJ,CAAC"}
|