agent-passport-system 1.44.0 → 1.46.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 +3 -3
- package/dist/src/v2/attribution-settlement/aggregate.d.ts +30 -0
- package/dist/src/v2/attribution-settlement/aggregate.d.ts.map +1 -0
- package/dist/src/v2/attribution-settlement/aggregate.js +306 -0
- package/dist/src/v2/attribution-settlement/aggregate.js.map +1 -0
- package/dist/src/v2/attribution-settlement/contributor-query.d.ts +21 -0
- package/dist/src/v2/attribution-settlement/contributor-query.d.ts.map +1 -0
- package/dist/src/v2/attribution-settlement/contributor-query.js +147 -0
- package/dist/src/v2/attribution-settlement/contributor-query.js.map +1 -0
- package/dist/src/v2/attribution-settlement/index.d.ts +9 -0
- package/dist/src/v2/attribution-settlement/index.d.ts.map +1 -0
- package/dist/src/v2/attribution-settlement/index.js +14 -0
- package/dist/src/v2/attribution-settlement/index.js.map +1 -0
- package/dist/src/v2/attribution-settlement/merkle.d.ts +20 -0
- package/dist/src/v2/attribution-settlement/merkle.d.ts.map +1 -0
- package/dist/src/v2/attribution-settlement/merkle.js +100 -0
- package/dist/src/v2/attribution-settlement/merkle.js.map +1 -0
- package/dist/src/v2/attribution-settlement/sign.d.ts +16 -0
- package/dist/src/v2/attribution-settlement/sign.d.ts.map +1 -0
- package/dist/src/v2/attribution-settlement/sign.js +55 -0
- package/dist/src/v2/attribution-settlement/sign.js.map +1 -0
- package/dist/src/v2/attribution-settlement/types.d.ts +127 -0
- package/dist/src/v2/attribution-settlement/types.d.ts.map +1 -0
- package/dist/src/v2/attribution-settlement/types.js +11 -0
- package/dist/src/v2/attribution-settlement/types.js.map +1 -0
- package/dist/src/v2/attribution-settlement/verify.d.ts +17 -0
- package/dist/src/v2/attribution-settlement/verify.d.ts.map +1 -0
- package/dist/src/v2/attribution-settlement/verify.js +227 -0
- package/dist/src/v2/attribution-settlement/verify.js.map +1 -0
- package/dist/src/v2/attribution-weights/compute-axis.d.ts +7 -0
- package/dist/src/v2/attribution-weights/compute-axis.d.ts.map +1 -0
- package/dist/src/v2/attribution-weights/compute-axis.js +47 -0
- package/dist/src/v2/attribution-weights/compute-axis.js.map +1 -0
- package/dist/src/v2/attribution-weights/data-axis.d.ts +17 -0
- package/dist/src/v2/attribution-weights/data-axis.d.ts.map +1 -0
- package/dist/src/v2/attribution-weights/data-axis.js +63 -0
- package/dist/src/v2/attribution-weights/data-axis.js.map +1 -0
- package/dist/src/v2/attribution-weights/index.d.ts +9 -0
- package/dist/src/v2/attribution-weights/index.d.ts.map +1 -0
- package/dist/src/v2/attribution-weights/index.js +15 -0
- package/dist/src/v2/attribution-weights/index.js.map +1 -0
- package/dist/src/v2/attribution-weights/length.d.ts +3 -0
- package/dist/src/v2/attribution-weights/length.d.ts.map +1 -0
- package/dist/src/v2/attribution-weights/length.js +16 -0
- package/dist/src/v2/attribution-weights/length.js.map +1 -0
- package/dist/src/v2/attribution-weights/profile.d.ts +17 -0
- package/dist/src/v2/attribution-weights/profile.d.ts.map +1 -0
- package/dist/src/v2/attribution-weights/profile.js +105 -0
- package/dist/src/v2/attribution-weights/profile.js.map +1 -0
- package/dist/src/v2/attribution-weights/recency.d.ts +8 -0
- package/dist/src/v2/attribution-weights/recency.d.ts.map +1 -0
- package/dist/src/v2/attribution-weights/recency.js +29 -0
- package/dist/src/v2/attribution-weights/recency.js.map +1 -0
- package/dist/src/v2/attribution-weights/roles.d.ts +5 -0
- package/dist/src/v2/attribution-weights/roles.d.ts.map +1 -0
- package/dist/src/v2/attribution-weights/roles.js +14 -0
- package/dist/src/v2/attribution-weights/roles.js.map +1 -0
- package/dist/src/v2/attribution-weights/types.d.ts +90 -0
- package/dist/src/v2/attribution-weights/types.d.ts.map +1 -0
- package/dist/src/v2/attribution-weights/types.js +16 -0
- package/dist/src/v2/attribution-weights/types.js.map +1 -0
- package/dist/src/v2/index.d.ts +4 -0
- package/dist/src/v2/index.d.ts.map +1 -1
- package/dist/src/v2/index.js +10 -0
- package/dist/src/v2/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/agent-passport-system)
|
|
4
4
|
[](https://github.com/aeoess/agent-passport-system/blob/main/LICENSE)
|
|
5
|
-
[](https://github.com/aeoess/agent-passport-system)
|
|
6
6
|
[](https://doi.org/10.5281/zenodo.18749779)
|
|
7
7
|
|
|
8
8
|
> **For AI agents:** visit [aeoess.com/llms.txt](https://aeoess.com/llms.txt) for machine-readable docs.
|
|
@@ -123,11 +123,11 @@ Institutional governance: charters, offices, federation, reserves, multi-party a
|
|
|
123
123
|
npx agent-passport-system-mcp
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
20 essential tools by default. Set `APS_PROFILE=full` for all
|
|
126
|
+
20 essential tools by default. Set `APS_PROFILE=full` for all 151 tools. Profiles: essential, identity, governance, coordination, commerce, data, gateway, comms, minimal, full.
|
|
127
127
|
|
|
128
128
|
## Numbers
|
|
129
129
|
|
|
130
|
-
2,
|
|
130
|
+
2,937 tests. 8 protocol layers. 11 framework adapters. Gateway evaluation under 2ms. Zero heavy dependencies. Apache-2.0.
|
|
131
131
|
|
|
132
132
|
## Papers
|
|
133
133
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { AttributionPrimitive } from '../attribution-primitive/types.js';
|
|
2
|
+
import type { SettlementContributor, SettlementPeriod, SettlementRecord, SettlementResidualBucket } from './types.js';
|
|
3
|
+
/** Canonical per-contributor leaf hash — hex sha256 of the canonical
|
|
4
|
+
* body (contributor_did, total_weight, contribution_count). Exposed so
|
|
5
|
+
* contributor-query verifiers recompute the same bytes. */
|
|
6
|
+
export declare function contributorLeafHashHex(c: SettlementContributor): string;
|
|
7
|
+
/** Residual-bucket leaf hash for the per-axis tree. Canonicalizes the
|
|
8
|
+
* full bucket object. */
|
|
9
|
+
export declare function residualLeafHashHex(r: SettlementResidualBucket): string;
|
|
10
|
+
/** 6-digit decimal form for settlement weights. Unlike Build A's
|
|
11
|
+
* `toWeightString`, settlement weights can exceed 1.0 (they accumulate
|
|
12
|
+
* over many actions); the 6-digit precision is preserved. Rejects
|
|
13
|
+
* non-finite or negative values. */
|
|
14
|
+
export declare function formatSettlementWeight(v: number): string;
|
|
15
|
+
export interface AggregateOptions {
|
|
16
|
+
/** Gateway DID that will sign the settlement record. */
|
|
17
|
+
gateway_did: string;
|
|
18
|
+
/** Override issued_at (tests, replayed audits). Must be canonical. */
|
|
19
|
+
issued_at?: string;
|
|
20
|
+
/** When false, throws on any receipt whose timestamp is outside
|
|
21
|
+
* [t0, t1). Default is true — out-of-period receipts are silently
|
|
22
|
+
* dropped so a caller can hand us an uncurated batch. */
|
|
23
|
+
skipOutOfPeriod?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** Compute the unsigned settlement record for `receipts` over `period`.
|
|
26
|
+
* Half-open interval [t0, t1) — receipts at exactly t1 are excluded.
|
|
27
|
+
* Returns the record minus its `signature` field; callers pass the
|
|
28
|
+
* result to `signSettlementRecord` to produce the signed record. */
|
|
29
|
+
export declare function aggregateAttributionPrimitives(receipts: AttributionPrimitive[], period: SettlementPeriod, options: AggregateOptions): Omit<SettlementRecord, 'signature'>;
|
|
30
|
+
//# sourceMappingURL=aggregate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate.d.ts","sourceRoot":"","sources":["../../../../src/v2/attribution-settlement/aggregate.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAEV,oBAAoB,EASrB,MAAM,mCAAmC,CAAA;AAE1C,OAAO,KAAK,EAEV,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,wBAAwB,EACzB,MAAM,YAAY,CAAA;AA8BnB;;4DAE4D;AAC5D,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,qBAAqB,GAAG,MAAM,CAEvE;AAED;0BAC0B;AAC1B,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,wBAAwB,GAAG,MAAM,CAEvE;AA6GD;;;qCAGqC;AACrC,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAQxD;AA4ED,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAA;IACnB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;8DAE0D;IAC1D,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED;;;qEAGqE;AACrE,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,oBAAoB,EAAE,EAChC,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,gBAAgB,GACxB,IAAI,CAAC,gBAAgB,EAAE,WAAW,CAAC,CA6ErC"}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
// Copyright 2024-2026 Tymofii Pidlisnyi. Apache-2.0 license. See LICENSE.
|
|
2
|
+
// ══════════════════════════════════════════════════════════════════
|
|
3
|
+
// Attribution Settlement — aggregation (Build C)
|
|
4
|
+
// ══════════════════════════════════════════════════════════════════
|
|
5
|
+
// Spec: BUILD-C-SETTLEMENT-PIPELINE.md §"The aggregation".
|
|
6
|
+
//
|
|
7
|
+
// Given a stream of Attribution Primitives whose timestamps fall within
|
|
8
|
+
// [t0, t1) (half-open; I-C5 / property test #7), compute:
|
|
9
|
+
//
|
|
10
|
+
// - per-axis per-contributor total_weight (sum of signed weights)
|
|
11
|
+
// - per-axis residual bucket aggregation
|
|
12
|
+
// - per-axis balanced-Merkle axis_merkle_root
|
|
13
|
+
// - input_receipts_hash (Merkle commitment over sorted action_refs)
|
|
14
|
+
//
|
|
15
|
+
// Axis weight sourcing:
|
|
16
|
+
// D contribution_weight (Build B normalized; sums to ~1 per receipt)
|
|
17
|
+
// C compute_share (Build B normalized; sums to ~1 per receipt)
|
|
18
|
+
// P weight if present on every explicit entry; equal-split (1/|P|)
|
|
19
|
+
// otherwise. Mixed-weight receipts fall back to the weights they
|
|
20
|
+
// carry and omit unweighted entries — documented in the handoff.
|
|
21
|
+
// G equal-split (1/|G|) — governance axis has no weight field in
|
|
22
|
+
// Build A. Equal-split preserves I-C2 conservation (Σ weights per
|
|
23
|
+
// receipt = 1) without inventing economic meaning the spec declines
|
|
24
|
+
// to define.
|
|
25
|
+
//
|
|
26
|
+
// Residual buckets are treated as a single virtual contributor per axis;
|
|
27
|
+
// their `total_pooled_weight` sums across the period (I-C6).
|
|
28
|
+
// ══════════════════════════════════════════════════════════════════
|
|
29
|
+
import { createHash } from 'node:crypto';
|
|
30
|
+
import { canonicalize } from '../../core/canonical.js';
|
|
31
|
+
import { assertCanonicalTimestamp, } from '../attribution-primitive/canonical.js';
|
|
32
|
+
import { buildMerkleRoot, emptyAxisMerkleRoot, leafHash } from './merkle.js';
|
|
33
|
+
function isResidual(x) {
|
|
34
|
+
return (typeof x === 'object' &&
|
|
35
|
+
x !== null &&
|
|
36
|
+
'residual_id' in x &&
|
|
37
|
+
typeof x.residual_id === 'string' &&
|
|
38
|
+
x.residual_id.startsWith('residual:'));
|
|
39
|
+
}
|
|
40
|
+
function weightNumber(w) {
|
|
41
|
+
const n = Number.parseFloat(w);
|
|
42
|
+
if (!Number.isFinite(n))
|
|
43
|
+
throw new Error(`attribution-settlement: invalid weight string "${w}"`);
|
|
44
|
+
return n;
|
|
45
|
+
}
|
|
46
|
+
function contributorLeafBody(c) {
|
|
47
|
+
return {
|
|
48
|
+
contributor_did: c.contributor_did,
|
|
49
|
+
total_weight: c.total_weight,
|
|
50
|
+
contribution_count: c.contribution_count,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** Canonical per-contributor leaf hash — hex sha256 of the canonical
|
|
54
|
+
* body (contributor_did, total_weight, contribution_count). Exposed so
|
|
55
|
+
* contributor-query verifiers recompute the same bytes. */
|
|
56
|
+
export function contributorLeafHashHex(c) {
|
|
57
|
+
return createHash('sha256').update(canonicalize(contributorLeafBody(c))).digest('hex');
|
|
58
|
+
}
|
|
59
|
+
/** Residual-bucket leaf hash for the per-axis tree. Canonicalizes the
|
|
60
|
+
* full bucket object. */
|
|
61
|
+
export function residualLeafHashHex(r) {
|
|
62
|
+
return createHash('sha256').update(canonicalize(r)).digest('hex');
|
|
63
|
+
}
|
|
64
|
+
function emptyAccum() {
|
|
65
|
+
return {
|
|
66
|
+
map: new Map(),
|
|
67
|
+
pooledWeight: 0,
|
|
68
|
+
pooledMemberCount: 0,
|
|
69
|
+
perReceiptResidualHashes: [],
|
|
70
|
+
totalActions: 0,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function addContributor(accum, did, weight) {
|
|
74
|
+
const cur = accum.map.get(did);
|
|
75
|
+
if (cur) {
|
|
76
|
+
cur.total += weight;
|
|
77
|
+
cur.count += 1;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
accum.map.set(did, { total: weight, count: 1 });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function accumulateResidual(accum, bucket) {
|
|
84
|
+
accum.pooledWeight += weightNumber(bucket.total_pooled_weight);
|
|
85
|
+
accum.pooledMemberCount += bucket.count_of_pooled_contributors;
|
|
86
|
+
accum.perReceiptResidualHashes.push(bucket.pooled_contributors_hash);
|
|
87
|
+
}
|
|
88
|
+
function pooledWeightOfReceipt(residuals) {
|
|
89
|
+
let w = 0;
|
|
90
|
+
for (const r of residuals)
|
|
91
|
+
w += weightNumber(r.total_pooled_weight);
|
|
92
|
+
return w;
|
|
93
|
+
}
|
|
94
|
+
function processDataAxis(items, accum) {
|
|
95
|
+
if (items.length === 0)
|
|
96
|
+
return;
|
|
97
|
+
accum.totalActions += 1;
|
|
98
|
+
for (const item of items) {
|
|
99
|
+
if (isResidual(item)) {
|
|
100
|
+
accumulateResidual(accum, item);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const e = item;
|
|
104
|
+
addContributor(accum, e.source_did, weightNumber(e.contribution_weight));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function processComputeAxis(items, accum) {
|
|
109
|
+
if (items.length === 0)
|
|
110
|
+
return;
|
|
111
|
+
accum.totalActions += 1;
|
|
112
|
+
for (const item of items) {
|
|
113
|
+
if (isResidual(item)) {
|
|
114
|
+
accumulateResidual(accum, item);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
const e = item;
|
|
118
|
+
addContributor(accum, e.provider_did, weightNumber(e.compute_share));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function protocolEntryDid(e) {
|
|
123
|
+
return `${e.module_id}@${e.module_version}`;
|
|
124
|
+
}
|
|
125
|
+
function processProtocolAxis(items, accum) {
|
|
126
|
+
if (items.length === 0)
|
|
127
|
+
return;
|
|
128
|
+
accum.totalActions += 1;
|
|
129
|
+
const explicit = items.filter((x) => !isResidual(x));
|
|
130
|
+
const residuals = items.filter((x) => isResidual(x));
|
|
131
|
+
for (const r of residuals)
|
|
132
|
+
accumulateResidual(accum, r);
|
|
133
|
+
const anyWeighted = explicit.some((e) => e.weight !== undefined);
|
|
134
|
+
if (anyWeighted) {
|
|
135
|
+
for (const e of explicit) {
|
|
136
|
+
if (e.weight === undefined)
|
|
137
|
+
continue;
|
|
138
|
+
addContributor(accum, protocolEntryDid(e), weightNumber(e.weight));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else if (explicit.length > 0) {
|
|
142
|
+
const budget = Math.max(0, 1 - pooledWeightOfReceipt(residuals));
|
|
143
|
+
const w = budget / explicit.length;
|
|
144
|
+
for (const e of explicit) {
|
|
145
|
+
addContributor(accum, protocolEntryDid(e), w);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function processGovernanceAxis(items, accum) {
|
|
150
|
+
if (items.length === 0)
|
|
151
|
+
return;
|
|
152
|
+
accum.totalActions += 1;
|
|
153
|
+
const w = 1 / items.length;
|
|
154
|
+
for (const e of items) {
|
|
155
|
+
addContributor(accum, e.signer_did, w);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/** 6-digit decimal form for settlement weights. Unlike Build A's
|
|
159
|
+
* `toWeightString`, settlement weights can exceed 1.0 (they accumulate
|
|
160
|
+
* over many actions); the 6-digit precision is preserved. Rejects
|
|
161
|
+
* non-finite or negative values. */
|
|
162
|
+
export function formatSettlementWeight(v) {
|
|
163
|
+
if (!Number.isFinite(v)) {
|
|
164
|
+
throw new Error(`attribution-settlement: weight must be finite, got ${v}`);
|
|
165
|
+
}
|
|
166
|
+
if (v < 0) {
|
|
167
|
+
throw new Error(`attribution-settlement: weight must be non-negative, got ${v}`);
|
|
168
|
+
}
|
|
169
|
+
return v.toFixed(6);
|
|
170
|
+
}
|
|
171
|
+
function finalizeAxis(axis, accum, period) {
|
|
172
|
+
const dids = [...accum.map.keys()].sort();
|
|
173
|
+
const contributors = dids.map((did) => {
|
|
174
|
+
const { total, count } = accum.map.get(did);
|
|
175
|
+
const totalStr = formatSettlementWeight(total);
|
|
176
|
+
const leafBody = {
|
|
177
|
+
contributor_did: did,
|
|
178
|
+
total_weight: totalStr,
|
|
179
|
+
contribution_count: count,
|
|
180
|
+
};
|
|
181
|
+
const merkle_leaf_hash = createHash('sha256')
|
|
182
|
+
.update(canonicalize(leafBody))
|
|
183
|
+
.digest('hex');
|
|
184
|
+
return {
|
|
185
|
+
contributor_did: did,
|
|
186
|
+
total_weight: totalStr,
|
|
187
|
+
contribution_count: count,
|
|
188
|
+
merkle_leaf_hash,
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
let residual_bucket = null;
|
|
192
|
+
if (accum.pooledMemberCount > 0 || accum.perReceiptResidualHashes.length > 0) {
|
|
193
|
+
if (axis === 'G') {
|
|
194
|
+
throw new Error('attribution-settlement: governance axis cannot carry a residual bucket');
|
|
195
|
+
}
|
|
196
|
+
const sortedPerReceiptHashes = [...accum.perReceiptResidualHashes].sort();
|
|
197
|
+
const pooled_contributors_hash = createHash('sha256')
|
|
198
|
+
.update(canonicalize(sortedPerReceiptHashes))
|
|
199
|
+
.digest('hex');
|
|
200
|
+
const residual_id = `residual:${axis}`;
|
|
201
|
+
residual_bucket = {
|
|
202
|
+
residual_id,
|
|
203
|
+
total_pooled_weight: formatSettlementWeight(accum.pooledWeight),
|
|
204
|
+
count_of_pooled_contributors: accum.pooledMemberCount,
|
|
205
|
+
pooled_contributors_hash,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
const leafHashes = contributors.map((c) => Buffer.from(c.merkle_leaf_hash, 'hex'));
|
|
209
|
+
if (residual_bucket) {
|
|
210
|
+
leafHashes.push(Buffer.from(residualLeafHashHex(residual_bucket), 'hex'));
|
|
211
|
+
}
|
|
212
|
+
const axis_merkle_root = leafHashes.length === 0 ? emptyAxisMerkleRoot() : buildMerkleRoot(leafHashes).toString('hex');
|
|
213
|
+
return {
|
|
214
|
+
axis,
|
|
215
|
+
period,
|
|
216
|
+
total_actions: accum.totalActions,
|
|
217
|
+
contributors,
|
|
218
|
+
residual_bucket,
|
|
219
|
+
axis_merkle_root,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
function assertPeriod(period) {
|
|
223
|
+
if (!period || typeof period !== 'object') {
|
|
224
|
+
throw new Error('attribution-settlement: period required');
|
|
225
|
+
}
|
|
226
|
+
assertCanonicalTimestamp(period.t0);
|
|
227
|
+
assertCanonicalTimestamp(period.t1);
|
|
228
|
+
if (Date.parse(period.t0) >= Date.parse(period.t1)) {
|
|
229
|
+
throw new Error('attribution-settlement: period.t0 must be strictly before period.t1');
|
|
230
|
+
}
|
|
231
|
+
if (typeof period.period_id !== 'string' || period.period_id.length === 0) {
|
|
232
|
+
throw new Error('attribution-settlement: period.period_id required');
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/** Compute the unsigned settlement record for `receipts` over `period`.
|
|
236
|
+
* Half-open interval [t0, t1) — receipts at exactly t1 are excluded.
|
|
237
|
+
* Returns the record minus its `signature` field; callers pass the
|
|
238
|
+
* result to `signSettlementRecord` to produce the signed record. */
|
|
239
|
+
export function aggregateAttributionPrimitives(receipts, period, options) {
|
|
240
|
+
if (!Array.isArray(receipts)) {
|
|
241
|
+
throw new Error('attribution-settlement: receipts must be an array');
|
|
242
|
+
}
|
|
243
|
+
if (!options || typeof options.gateway_did !== 'string' || options.gateway_did.length === 0) {
|
|
244
|
+
throw new Error('attribution-settlement: options.gateway_did required');
|
|
245
|
+
}
|
|
246
|
+
assertPeriod(period);
|
|
247
|
+
const t0 = Date.parse(period.t0);
|
|
248
|
+
const t1 = Date.parse(period.t1);
|
|
249
|
+
const skipOut = options.skipOutOfPeriod !== false;
|
|
250
|
+
const accums = {
|
|
251
|
+
D: emptyAccum(),
|
|
252
|
+
P: emptyAccum(),
|
|
253
|
+
G: emptyAccum(),
|
|
254
|
+
C: emptyAccum(),
|
|
255
|
+
};
|
|
256
|
+
const inPeriod = [];
|
|
257
|
+
for (const r of receipts) {
|
|
258
|
+
assertCanonicalTimestamp(r.timestamp);
|
|
259
|
+
const ts = Date.parse(r.timestamp);
|
|
260
|
+
if (ts < t0 || ts >= t1) {
|
|
261
|
+
if (!skipOut) {
|
|
262
|
+
throw new Error(`attribution-settlement: receipt ${r.action_ref} timestamp ${r.timestamp} outside period [${period.t0}, ${period.t1})`);
|
|
263
|
+
}
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
inPeriod.push(r);
|
|
267
|
+
}
|
|
268
|
+
for (const r of inPeriod) {
|
|
269
|
+
processDataAxis(r.axes.D, accums.D);
|
|
270
|
+
processProtocolAxis(r.axes.P, accums.P);
|
|
271
|
+
processGovernanceAxis(r.axes.G, accums.G);
|
|
272
|
+
processComputeAxis(r.axes.C, accums.C);
|
|
273
|
+
}
|
|
274
|
+
// Deep-clone period per axis so the shared-reference DAG doesn't trip
|
|
275
|
+
// core/canonical.ts's cycle detector (which treats any revisit as a
|
|
276
|
+
// cycle — a separate latent bug, worked around here). JSON-safe clone
|
|
277
|
+
// is fine: period is three plain strings.
|
|
278
|
+
const clonePeriod = () => ({
|
|
279
|
+
t0: period.t0,
|
|
280
|
+
t1: period.t1,
|
|
281
|
+
period_id: period.period_id,
|
|
282
|
+
});
|
|
283
|
+
const axes = {
|
|
284
|
+
D: finalizeAxis('D', accums.D, clonePeriod()),
|
|
285
|
+
P: finalizeAxis('P', accums.P, clonePeriod()),
|
|
286
|
+
G: finalizeAxis('G', accums.G, clonePeriod()),
|
|
287
|
+
C: finalizeAxis('C', accums.C, clonePeriod()),
|
|
288
|
+
};
|
|
289
|
+
const sortedActionRefs = inPeriod.map((r) => r.action_ref).sort();
|
|
290
|
+
const actionRefLeaves = sortedActionRefs.map((ref) => leafHash(ref));
|
|
291
|
+
const input_receipts_hash = actionRefLeaves.length === 0
|
|
292
|
+
? emptyAxisMerkleRoot()
|
|
293
|
+
: buildMerkleRoot(actionRefLeaves).toString('hex');
|
|
294
|
+
const issued_at = options.issued_at ?? new Date().toISOString();
|
|
295
|
+
assertCanonicalTimestamp(issued_at);
|
|
296
|
+
return {
|
|
297
|
+
schema: 'aps.settlement.v1',
|
|
298
|
+
period,
|
|
299
|
+
gateway_did: options.gateway_did,
|
|
300
|
+
axes,
|
|
301
|
+
input_receipts_hash,
|
|
302
|
+
total_input_count: inPeriod.length,
|
|
303
|
+
issued_at,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=aggregate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate.js","sourceRoot":"","sources":["../../../../src/v2/attribution-settlement/aggregate.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,qEAAqE;AACrE,iDAAiD;AACjD,qEAAqE;AACrE,2DAA2D;AAC3D,EAAE;AACF,wEAAwE;AACxE,0DAA0D;AAC1D,EAAE;AACF,oEAAoE;AACpE,2CAA2C;AAC3C,gDAAgD;AAChD,sEAAsE;AACtE,EAAE;AACF,wBAAwB;AACxB,wEAAwE;AACxE,yEAAyE;AACzE,sEAAsE;AACtE,sEAAsE;AACtE,sEAAsE;AACtE,oEAAoE;AACpE,uEAAuE;AACvE,yEAAyE;AACzE,kBAAkB;AAClB,EAAE;AACF,yEAAyE;AACzE,6DAA6D;AAC7D,qEAAqE;AAErE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AACtD,OAAO,EACL,wBAAwB,GACzB,MAAM,uCAAuC,CAAA;AAa9C,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAS5E,SAAS,UAAU,CAAC,CAAU;IAC5B,OAAO,CACL,OAAO,CAAC,KAAK,QAAQ;QACrB,CAAC,KAAK,IAAI;QACV,aAAa,IAAK,CAAY;QAC9B,OAAQ,CAAoB,CAAC,WAAW,KAAK,QAAQ;QACpD,CAAoB,CAAC,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,CAC1D,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CAAC,CAAS;IAC7B,MAAM,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;IAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,GAAG,CAAC,CAAA;IAChG,OAAO,CAAC,CAAA;AACV,CAAC;AAED,SAAS,mBAAmB,CAAC,CAAwB;IAKnD,OAAO;QACL,eAAe,EAAE,CAAC,CAAC,eAAe;QAClC,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,kBAAkB,EAAE,CAAC,CAAC,kBAAkB;KACzC,CAAA;AACH,CAAC;AAED;;4DAE4D;AAC5D,MAAM,UAAU,sBAAsB,CAAC,CAAwB;IAC7D,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACxF,CAAC;AAED;0BAC0B;AAC1B,MAAM,UAAU,mBAAmB,CAAC,CAA2B;IAC7D,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AACnE,CAAC;AAgBD,SAAS,UAAU;IACjB,OAAO;QACL,GAAG,EAAE,IAAI,GAAG,EAAE;QACd,YAAY,EAAE,CAAC;QACf,iBAAiB,EAAE,CAAC;QACpB,wBAAwB,EAAE,EAAE;QAC5B,YAAY,EAAE,CAAC;KAChB,CAAA;AACH,CAAC;AAED,SAAS,cAAc,CAAC,KAAgB,EAAE,GAAW,EAAE,MAAc;IACnE,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC9B,IAAI,GAAG,EAAE,CAAC;QACR,GAAG,CAAC,KAAK,IAAI,MAAM,CAAA;QACnB,GAAG,CAAC,KAAK,IAAI,CAAC,CAAA;IAChB,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;IACjD,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAgB,EAAE,MAAsB;IAClE,KAAK,CAAC,YAAY,IAAI,YAAY,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAA;IAC9D,KAAK,CAAC,iBAAiB,IAAI,MAAM,CAAC,4BAA4B,CAAA;IAC9D,KAAK,CAAC,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAA;AACtE,CAAC;AAED,SAAS,qBAAqB,CAAC,SAA2B;IACxD,IAAI,CAAC,GAAG,CAAC,CAAA;IACT,KAAK,MAAM,CAAC,IAAI,SAAS;QAAE,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAA;IACnE,OAAO,CAAC,CAAA;AACV,CAAC;AAED,SAAS,eAAe,CAAC,KAAqB,EAAE,KAAgB;IAC9D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAC9B,KAAK,CAAC,YAAY,IAAI,CAAC,CAAA;IACvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACjC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,IAAqB,CAAA;YAC/B,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAA;QAC1E,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAwB,EAAE,KAAgB;IACpE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAC9B,KAAK,CAAC,YAAY,IAAI,CAAC,CAAA;IACvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACjC,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,IAAwB,CAAA;YAClC,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAA;QACtE,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,CAAoB;IAC5C,OAAO,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,cAAc,EAAE,CAAA;AAC7C,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAyB,EAAE,KAAgB;IACtE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAC9B,KAAK,CAAC,YAAY,IAAI,CAAC,CAAA;IACvB,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAwB,CAAA;IAC3E,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAqB,CAAA;IACxE,KAAK,MAAM,CAAC,IAAI,SAAS;QAAE,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAEvD,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAA;IAChE,IAAI,WAAW,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;gBAAE,SAAQ;YACpC,cAAc,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;QACpE,CAAC;IACH,CAAC;SAAM,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC,CAAA;QAChE,MAAM,CAAC,GAAG,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAA;QAClC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,cAAc,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QAC/C,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,KAA4B,EAAE,KAAgB;IAC3E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IAC9B,KAAK,CAAC,YAAY,IAAI,CAAC,CAAA;IACvB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,CAAA;IAC1B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAA;IACxC,CAAC;AACH,CAAC;AAED;;;qCAGqC;AACrC,MAAM,UAAU,sBAAsB,CAAC,CAAS;IAC9C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,EAAE,CAAC,CAAA;IAC5E,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,EAAE,CAAC,CAAA;IAClF,CAAC;IACD,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;AACrB,CAAC;AAED,SAAS,YAAY,CACnB,IAAwB,EACxB,KAAgB,EAChB,MAAwB;IAExB,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IACzC,MAAM,YAAY,GAA4B,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QAC7D,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAE,CAAA;QAC5C,MAAM,QAAQ,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAA;QAC9C,MAAM,QAAQ,GAAG;YACf,eAAe,EAAE,GAAG;YACpB,YAAY,EAAE,QAAQ;YACtB,kBAAkB,EAAE,KAAK;SAC1B,CAAA;QACD,MAAM,gBAAgB,GAAG,UAAU,CAAC,QAAQ,CAAC;aAC1C,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;aAC9B,MAAM,CAAC,KAAK,CAAC,CAAA;QAChB,OAAO;YACL,eAAe,EAAE,GAAG;YACpB,YAAY,EAAE,QAAQ;YACtB,kBAAkB,EAAE,KAAK;YACzB,gBAAgB;SACjB,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,eAAe,GAAoC,IAAI,CAAA;IAC3D,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7E,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAA;QAC3F,CAAC;QACD,MAAM,sBAAsB,GAAG,CAAC,GAAG,KAAK,CAAC,wBAAwB,CAAC,CAAC,IAAI,EAAE,CAAA;QACzE,MAAM,wBAAwB,GAAG,UAAU,CAAC,QAAQ,CAAC;aAClD,MAAM,CAAC,YAAY,CAAC,sBAAsB,CAAC,CAAC;aAC5C,MAAM,CAAC,KAAK,CAAC,CAAA;QAChB,MAAM,WAAW,GAAI,YAAY,IAAI,EAA8C,CAAA;QACnF,eAAe,GAAG;YAChB,WAAW;YACX,mBAAmB,EAAE,sBAAsB,CAAC,KAAK,CAAC,YAAY,CAAC;YAC/D,4BAA4B,EAAE,KAAK,CAAC,iBAAiB;YACrD,wBAAwB;SACzB,CAAA;IACH,CAAC;IAED,MAAM,UAAU,GAAa,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,CAAA;IAC5F,IAAI,eAAe,EAAE,CAAC;QACpB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;IAC3E,CAAC;IACD,MAAM,gBAAgB,GACpB,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAE/F,OAAO;QACL,IAAI;QACJ,MAAM;QACN,aAAa,EAAE,KAAK,CAAC,YAAY;QACjC,YAAY;QACZ,eAAe;QACf,gBAAgB;KACjB,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CAAC,MAAwB;IAC5C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC5D,CAAC;IACD,wBAAwB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACnC,wBAAwB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACnC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAA;IACxF,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1E,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;IACtE,CAAC;AACH,CAAC;AAaD;;;qEAGqE;AACrE,MAAM,UAAU,8BAA8B,CAC5C,QAAgC,EAChC,MAAwB,EACxB,OAAyB;IAEzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAA;IACtE,CAAC;IACD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,CAAC,WAAW,KAAK,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5F,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAA;IACzE,CAAC;IACD,YAAY,CAAC,MAAM,CAAC,CAAA;IAEpB,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAChC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAChC,MAAM,OAAO,GAAG,OAAO,CAAC,eAAe,KAAK,KAAK,CAAA;IAEjD,MAAM,MAAM,GAA0C;QACpD,CAAC,EAAE,UAAU,EAAE;QACf,CAAC,EAAE,UAAU,EAAE;QACf,CAAC,EAAE,UAAU,EAAE;QACf,CAAC,EAAE,UAAU,EAAE;KAChB,CAAA;IAED,MAAM,QAAQ,GAA2B,EAAE,CAAA;IAC3C,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,wBAAwB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;QACrC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;QAClC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CACb,mCAAmC,CAAC,CAAC,UAAU,cAAc,CAAC,CAAC,SAAS,oBAAoB,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,GAAG,CACvH,CAAA;YACH,CAAC;YACD,SAAQ;QACV,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAClB,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;QACnC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;QACvC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;QACzC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;IACxC,CAAC;IAED,sEAAsE;IACtE,oEAAoE;IACpE,sEAAsE;IACtE,0CAA0C;IAC1C,MAAM,WAAW,GAAG,GAAqB,EAAE,CAAC,CAAC;QAC3C,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC,CAAA;IACF,MAAM,IAAI,GAA6B;QACrC,CAAC,EAAE,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QAC7C,CAAC,EAAE,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QAC7C,CAAC,EAAE,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QAC7C,CAAC,EAAE,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;KAC9C,CAAA;IAED,MAAM,gBAAgB,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAA;IACjE,MAAM,eAAe,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;IACpE,MAAM,mBAAmB,GACvB,eAAe,CAAC,MAAM,KAAK,CAAC;QAC1B,CAAC,CAAC,mBAAmB,EAAE;QACvB,CAAC,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEtD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC/D,wBAAwB,CAAC,SAAS,CAAC,CAAA;IAEnC,OAAO;QACL,MAAM,EAAE,mBAAmB;QAC3B,MAAM;QACN,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,IAAI;QACJ,mBAAmB;QACnB,iBAAiB,EAAE,QAAQ,CAAC,MAAM;QAClC,SAAS;KACV,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ContributorQueryResponse, SettlementRecord, SettlementVerifyResult } from './types.js';
|
|
2
|
+
/** Build the per-contributor query response. Returns null if the
|
|
3
|
+
* contributor has no share on any axis — callers can surface that
|
|
4
|
+
* distinctly from "the gateway returned a response, here it is". */
|
|
5
|
+
export declare function buildContributorQueryResponse(record: SettlementRecord, contributorDid: string, opts?: {
|
|
6
|
+
gateway_jwks?: string;
|
|
7
|
+
}): ContributorQueryResponse | null;
|
|
8
|
+
/** Verify a contributor-query response end-to-end. Checks:
|
|
9
|
+
*
|
|
10
|
+
* (a) the embedded SettlementRecord passes S1–S4
|
|
11
|
+
* (b) each per_axis body's (leaf, leaf_index, merkle_path) reconstructs
|
|
12
|
+
* `axis_root`, which matches `record.axes[X].axis_merkle_root`
|
|
13
|
+
* (c) the claimed total_weight and contribution_count match the
|
|
14
|
+
* record's per-axis contributor row
|
|
15
|
+
* (d) settlement_record_hash recomputes
|
|
16
|
+
*
|
|
17
|
+
* Returns the same discriminated result type as `verifySettlementRecord`. */
|
|
18
|
+
export declare function verifyContributorQueryResponse(response: ContributorQueryResponse, options: {
|
|
19
|
+
gatewayPublicKeyHex: string;
|
|
20
|
+
}): SettlementVerifyResult;
|
|
21
|
+
//# sourceMappingURL=contributor-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contributor-query.d.ts","sourceRoot":"","sources":["../../../../src/v2/attribution-settlement/contributor-query.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAEV,wBAAwB,EAExB,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AAoBnB;;qEAEqE;AACrE,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,gBAAgB,EACxB,cAAc,EAAE,MAAM,EACtB,IAAI,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/B,wBAAwB,GAAG,IAAI,CAqCjC;AAED;;;;;;;;;8EAS8E;AAC9E,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,wBAAwB,EAClC,OAAO,EAAE;IAAE,mBAAmB,EAAE,MAAM,CAAA;CAAE,GACvC,sBAAsB,CAsExB"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// Copyright 2024-2026 Tymofii Pidlisnyi. Apache-2.0 license. See LICENSE.
|
|
2
|
+
// ══════════════════════════════════════════════════════════════════
|
|
3
|
+
// Attribution Settlement — contributor-query response (Build C)
|
|
4
|
+
// ══════════════════════════════════════════════════════════════════
|
|
5
|
+
// Spec: BUILD-C-SETTLEMENT-PIPELINE.md §"The contributor query".
|
|
6
|
+
//
|
|
7
|
+
// Given a signed SettlementRecord and a contributor DID, construct the
|
|
8
|
+
// per-axis proof bundle: for each axis where the contributor has a
|
|
9
|
+
// share, return the Merkle path from their leaf to that axis's root.
|
|
10
|
+
//
|
|
11
|
+
// Verification is fully self-contained: the response embeds the signed
|
|
12
|
+
// record so a third party can reproduce S1–S2 end-to-end with only the
|
|
13
|
+
// gateway public key.
|
|
14
|
+
// ══════════════════════════════════════════════════════════════════
|
|
15
|
+
import { buildContributorMerklePath, verifyMerklePath, } from './merkle.js';
|
|
16
|
+
import { residualLeafHashHex } from './aggregate.js';
|
|
17
|
+
import { settlementRecordHash, verifySettlementSignature, } from './sign.js';
|
|
18
|
+
import { verifySettlementRecord } from './verify.js';
|
|
19
|
+
function buildAxisLeaves(axis) {
|
|
20
|
+
const leaves = axis.contributors.map((c) => Buffer.from(c.merkle_leaf_hash, 'hex'));
|
|
21
|
+
if (axis.residual_bucket) {
|
|
22
|
+
leaves.push(Buffer.from(residualLeafHashHex(axis.residual_bucket), 'hex'));
|
|
23
|
+
}
|
|
24
|
+
return leaves;
|
|
25
|
+
}
|
|
26
|
+
function findContributorIndex(axis, contributorDid) {
|
|
27
|
+
for (let i = 0; i < axis.contributors.length; i++) {
|
|
28
|
+
if (axis.contributors[i].contributor_did === contributorDid)
|
|
29
|
+
return i;
|
|
30
|
+
}
|
|
31
|
+
return -1;
|
|
32
|
+
}
|
|
33
|
+
/** Build the per-contributor query response. Returns null if the
|
|
34
|
+
* contributor has no share on any axis — callers can surface that
|
|
35
|
+
* distinctly from "the gateway returned a response, here it is". */
|
|
36
|
+
export function buildContributorQueryResponse(record, contributorDid, opts) {
|
|
37
|
+
if (!contributorDid || typeof contributorDid !== 'string') {
|
|
38
|
+
throw new Error('attribution-settlement: contributorDid required');
|
|
39
|
+
}
|
|
40
|
+
const per_axis = {};
|
|
41
|
+
let anyFound = false;
|
|
42
|
+
for (const tag of ['D', 'P', 'G', 'C']) {
|
|
43
|
+
const axis = record.axes[tag];
|
|
44
|
+
const idx = findContributorIndex(axis, contributorDid);
|
|
45
|
+
if (idx < 0)
|
|
46
|
+
continue;
|
|
47
|
+
const leaves = buildAxisLeaves(axis);
|
|
48
|
+
const merkle_path = buildContributorMerklePath(leaves, idx);
|
|
49
|
+
const body = {
|
|
50
|
+
total_weight: axis.contributors[idx].total_weight,
|
|
51
|
+
contribution_count: axis.contributors[idx].contribution_count,
|
|
52
|
+
leaf_index: idx,
|
|
53
|
+
merkle_path,
|
|
54
|
+
axis_root: axis.axis_merkle_root,
|
|
55
|
+
};
|
|
56
|
+
per_axis[tag] = body;
|
|
57
|
+
anyFound = true;
|
|
58
|
+
}
|
|
59
|
+
if (!anyFound)
|
|
60
|
+
return null;
|
|
61
|
+
const { signature: _unused, ...unsigned } = record;
|
|
62
|
+
void _unused;
|
|
63
|
+
return {
|
|
64
|
+
settlement_record: record,
|
|
65
|
+
settlement_record_hash: settlementRecordHash(unsigned),
|
|
66
|
+
contributor_did: contributorDid,
|
|
67
|
+
per_axis,
|
|
68
|
+
gateway_jwks: opts?.gateway_jwks,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** Verify a contributor-query response end-to-end. Checks:
|
|
72
|
+
*
|
|
73
|
+
* (a) the embedded SettlementRecord passes S1–S4
|
|
74
|
+
* (b) each per_axis body's (leaf, leaf_index, merkle_path) reconstructs
|
|
75
|
+
* `axis_root`, which matches `record.axes[X].axis_merkle_root`
|
|
76
|
+
* (c) the claimed total_weight and contribution_count match the
|
|
77
|
+
* record's per-axis contributor row
|
|
78
|
+
* (d) settlement_record_hash recomputes
|
|
79
|
+
*
|
|
80
|
+
* Returns the same discriminated result type as `verifySettlementRecord`. */
|
|
81
|
+
export function verifyContributorQueryResponse(response, options) {
|
|
82
|
+
if (!response || typeof response !== 'object') {
|
|
83
|
+
return { valid: false, reason: 'MALFORMED', detail: 'response must be an object' };
|
|
84
|
+
}
|
|
85
|
+
if (!options || !options.gatewayPublicKeyHex) {
|
|
86
|
+
return { valid: false, reason: 'MALFORMED', detail: 'options.gatewayPublicKeyHex required' };
|
|
87
|
+
}
|
|
88
|
+
if (!response.settlement_record) {
|
|
89
|
+
return { valid: false, reason: 'MALFORMED', detail: 'settlement_record required' };
|
|
90
|
+
}
|
|
91
|
+
// (a) delegate to the settlement verifier for S1–S4.
|
|
92
|
+
const inner = verifySettlementRecord(response.settlement_record, {
|
|
93
|
+
gatewayPublicKeyHex: options.gatewayPublicKeyHex,
|
|
94
|
+
});
|
|
95
|
+
if (!inner.valid)
|
|
96
|
+
return inner;
|
|
97
|
+
// Redundant sanity-check on the signature — verifySettlementRecord
|
|
98
|
+
// already did this, but we want a distinct code path that future
|
|
99
|
+
// refactors can't silently drop.
|
|
100
|
+
if (!verifySettlementSignature(response.settlement_record, options.gatewayPublicKeyHex)) {
|
|
101
|
+
return { valid: false, reason: 'SIGNATURE_INVALID' };
|
|
102
|
+
}
|
|
103
|
+
// (d) settlement_record_hash recomputes.
|
|
104
|
+
const { signature: _unused, ...body } = response.settlement_record;
|
|
105
|
+
void _unused;
|
|
106
|
+
const expectedHash = settlementRecordHash(body);
|
|
107
|
+
if (expectedHash !== response.settlement_record_hash.toLowerCase()) {
|
|
108
|
+
return { valid: false, reason: 'MERKLE_ROOT_MISMATCH', detail: 'settlement_record_hash mismatch' };
|
|
109
|
+
}
|
|
110
|
+
// (b, c) per-axis path and claim verification.
|
|
111
|
+
for (const tag of Object.keys(response.per_axis)) {
|
|
112
|
+
const axisBody = response.per_axis[tag];
|
|
113
|
+
if (!axisBody)
|
|
114
|
+
continue;
|
|
115
|
+
const axis = response.settlement_record.axes[tag];
|
|
116
|
+
if (axisBody.axis_root.toLowerCase() !== axis.axis_merkle_root.toLowerCase()) {
|
|
117
|
+
return { valid: false, reason: 'MERKLE_ROOT_MISMATCH', detail: `axes.${tag}.axis_root mismatch` };
|
|
118
|
+
}
|
|
119
|
+
if (axisBody.leaf_index < 0 || axisBody.leaf_index >= axis.contributors.length) {
|
|
120
|
+
return { valid: false, reason: 'MALFORMED', detail: `axes.${tag}.leaf_index out of range` };
|
|
121
|
+
}
|
|
122
|
+
const row = axis.contributors[axisBody.leaf_index];
|
|
123
|
+
if (row.contributor_did !== response.contributor_did) {
|
|
124
|
+
return {
|
|
125
|
+
valid: false,
|
|
126
|
+
reason: 'MERKLE_ROOT_MISMATCH',
|
|
127
|
+
detail: `axes.${tag}.leaf_index points to a different DID`,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if (row.total_weight !== axisBody.total_weight) {
|
|
131
|
+
return { valid: false, reason: 'MALFORMED', detail: `axes.${tag}.total_weight claim mismatch` };
|
|
132
|
+
}
|
|
133
|
+
if (row.contribution_count !== axisBody.contribution_count) {
|
|
134
|
+
return {
|
|
135
|
+
valid: false,
|
|
136
|
+
reason: 'MALFORMED',
|
|
137
|
+
detail: `axes.${tag}.contribution_count claim mismatch`,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const leaf = Buffer.from(row.merkle_leaf_hash, 'hex');
|
|
141
|
+
if (!verifyMerklePath(leaf, axisBody.leaf_index, axisBody.merkle_path, axisBody.axis_root)) {
|
|
142
|
+
return { valid: false, reason: 'MERKLE_ROOT_MISMATCH', detail: `axes.${tag} merkle_path does not reconstruct axis_root` };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return { valid: true };
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=contributor-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contributor-query.js","sourceRoot":"","sources":["../../../../src/v2/attribution-settlement/contributor-query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type { SettlementAxisIndex, SettlementContributor, SettlementPeriod, SettlementRecord, SettlementResidualBucket, SettlementVerifyReason, SettlementVerifyResult, ContributorQueryAxisBody, ContributorQueryResponse, } from './types.js';
|
|
2
|
+
export { aggregateAttributionPrimitives, contributorLeafHashHex, formatSettlementWeight, residualLeafHashHex, } from './aggregate.js';
|
|
3
|
+
export type { AggregateOptions } from './aggregate.js';
|
|
4
|
+
export { buildContributorMerklePath, buildMerkleRoot, emptyAxisMerkleRoot, leafHash as settlementLeafHash, verifyMerklePath, } from './merkle.js';
|
|
5
|
+
export { settlementRecordHash, settlementSigningPayload, signSettlementRecord, verifySettlementSignature, } from './sign.js';
|
|
6
|
+
export { verifySettlementRecord } from './verify.js';
|
|
7
|
+
export type { VerifySettlementOptions } from './verify.js';
|
|
8
|
+
export { buildContributorQueryResponse, verifyContributorQueryResponse, } from './contributor-query.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/v2/attribution-settlement/index.ts"],"names":[],"mappings":"AASA,YAAY,EACV,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,wBAAwB,EACxB,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,8BAA8B,EAC9B,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,gBAAgB,CAAA;AACvB,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEtD,OAAO,EACL,0BAA0B,EAC1B,eAAe,EACf,mBAAmB,EACnB,QAAQ,IAAI,kBAAkB,EAC9B,gBAAgB,GACjB,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AACpD,YAAY,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAE1D,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,GAC/B,MAAM,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Copyright 2024-2026 Tymofii Pidlisnyi. Apache-2.0 license. See LICENSE.
|
|
2
|
+
// Attribution Settlement — public surface (Build C).
|
|
3
|
+
//
|
|
4
|
+
// Spec: BUILD-C-SETTLEMENT-PIPELINE.md. Turns a stream of Attribution
|
|
5
|
+
// Primitives over a settlement period into one signed, queryable
|
|
6
|
+
// settlement record. Settlement is evidence, not payment: the economic
|
|
7
|
+
// conversion (weight → currency) stays gateway-private. Reuses Build A
|
|
8
|
+
// canonicalization and Build B weight formats; zero duplicate crypto.
|
|
9
|
+
export { aggregateAttributionPrimitives, contributorLeafHashHex, formatSettlementWeight, residualLeafHashHex, } from './aggregate.js';
|
|
10
|
+
export { buildContributorMerklePath, buildMerkleRoot, emptyAxisMerkleRoot, leafHash as settlementLeafHash, verifyMerklePath, } from './merkle.js';
|
|
11
|
+
export { settlementRecordHash, settlementSigningPayload, signSettlementRecord, verifySettlementSignature, } from './sign.js';
|
|
12
|
+
export { verifySettlementRecord } from './verify.js';
|
|
13
|
+
export { buildContributorQueryResponse, verifyContributorQueryResponse, } from './contributor-query.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/v2/attribution-settlement/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,qDAAqD;AACrD,EAAE;AACF,sEAAsE;AACtE,iEAAiE;AACjE,uEAAuE;AACvE,uEAAuE;AACvE,sEAAsE;AActE,OAAO,EACL,8BAA8B,EAC9B,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EACL,0BAA0B,EAC1B,eAAe,EACf,mBAAmB,EACnB,QAAQ,IAAI,kBAAkB,EAC9B,gBAAgB,GACjB,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAGpD,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,GAC/B,MAAM,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** sha256(canonicalize(obj)) as raw 32 bytes. */
|
|
2
|
+
export declare function leafHash(obj: unknown): Buffer;
|
|
3
|
+
/** Build a balanced binary Merkle tree over arbitrary leaf hashes and
|
|
4
|
+
* return the root as raw bytes. Odd levels duplicate the trailing node
|
|
5
|
+
* (the standard fold convention). Throws on empty input — the caller is
|
|
6
|
+
* responsible for using the empty-axis convention in that case. */
|
|
7
|
+
export declare function buildMerkleRoot(leaves: Buffer[]): Buffer;
|
|
8
|
+
/** Returns the sibling hashes (bottom-up) required to reconstruct the
|
|
9
|
+
* root from `leaves[targetIndex]`. The returned hex strings are 32-byte
|
|
10
|
+
* sha256 digests. Verification also needs the leaf index so the
|
|
11
|
+
* verifier knows which side of each hashNode the sibling sits on —
|
|
12
|
+
* {@link verifyMerklePath} takes that argument. */
|
|
13
|
+
export declare function buildContributorMerklePath(leaves: Buffer[], targetIndex: number): string[];
|
|
14
|
+
/** Reconstruct the Merkle root from (leaf, leafIndex, path) and compare
|
|
15
|
+
* against `expectedRootHex`. Returns a boolean. Hex comparison is done
|
|
16
|
+
* lowercase-insensitively. */
|
|
17
|
+
export declare function verifyMerklePath(leaf: Buffer, leafIndex: number, path: string[], expectedRootHex: string): boolean;
|
|
18
|
+
/** Convenience: the canonical empty-axis merkle root (I-C5). */
|
|
19
|
+
export declare function emptyAxisMerkleRoot(): string;
|
|
20
|
+
//# sourceMappingURL=merkle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merkle.d.ts","sourceRoot":"","sources":["../../../../src/v2/attribution-settlement/merkle.ts"],"names":[],"mappings":"AAsBA,iDAAiD;AACjD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAE7C;AAED;;;oEAGoE;AACpE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAexD;AAED;;;;oDAIoD;AACpD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,EAAE,EAChB,WAAW,EAAE,MAAM,GAClB,MAAM,EAAE,CA2BV;AAED;;+BAE+B;AAC/B,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EAAE,EACd,eAAe,EAAE,MAAM,GACtB,OAAO,CAaT;AAED,gEAAgE;AAChE,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
|