agent-passport-system 1.43.0 → 1.44.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 +2 -2
- package/dist/src/v2/attribution-primitive/canonical.d.ts +45 -0
- package/dist/src/v2/attribution-primitive/canonical.d.ts.map +1 -0
- package/dist/src/v2/attribution-primitive/canonical.js +142 -0
- package/dist/src/v2/attribution-primitive/canonical.js.map +1 -0
- package/dist/src/v2/attribution-primitive/construct.d.ts +37 -0
- package/dist/src/v2/attribution-primitive/construct.d.ts.map +1 -0
- package/dist/src/v2/attribution-primitive/construct.js +89 -0
- package/dist/src/v2/attribution-primitive/construct.js.map +1 -0
- package/dist/src/v2/attribution-primitive/index.d.ts +11 -0
- package/dist/src/v2/attribution-primitive/index.d.ts.map +1 -0
- package/dist/src/v2/attribution-primitive/index.js +13 -0
- package/dist/src/v2/attribution-primitive/index.js.map +1 -0
- package/dist/src/v2/attribution-primitive/merkle.d.ts +28 -0
- package/dist/src/v2/attribution-primitive/merkle.d.ts.map +1 -0
- package/dist/src/v2/attribution-primitive/merkle.js +76 -0
- package/dist/src/v2/attribution-primitive/merkle.js.map +1 -0
- package/dist/src/v2/attribution-primitive/project.d.ts +24 -0
- package/dist/src/v2/attribution-primitive/project.d.ts.map +1 -0
- package/dist/src/v2/attribution-primitive/project.js +84 -0
- package/dist/src/v2/attribution-primitive/project.js.map +1 -0
- package/dist/src/v2/attribution-primitive/residual.d.ts +28 -0
- package/dist/src/v2/attribution-primitive/residual.d.ts.map +1 -0
- package/dist/src/v2/attribution-primitive/residual.js +148 -0
- package/dist/src/v2/attribution-primitive/residual.js.map +1 -0
- package/dist/src/v2/attribution-primitive/types.d.ts +133 -0
- package/dist/src/v2/attribution-primitive/types.d.ts.map +1 -0
- package/dist/src/v2/attribution-primitive/types.js +14 -0
- package/dist/src/v2/attribution-primitive/types.js.map +1 -0
- package/dist/src/v2/attribution-primitive/verify.d.ts +15 -0
- package/dist/src/v2/attribution-primitive/verify.d.ts.map +1 -0
- package/dist/src/v2/attribution-primitive/verify.js +110 -0
- package/dist/src/v2/attribution-primitive/verify.js.map +1 -0
- package/dist/src/v2/index.d.ts +2 -0
- package/dist/src/v2/index.d.ts.map +1 -1
- package/dist/src/v2/index.js +5 -0
- package/dist/src/v2/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -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 149 tools. Profiles: essential, identity, governance, coordination, commerce, data, gateway, comms, minimal, full.
|
|
127
127
|
|
|
128
128
|
## Numbers
|
|
129
129
|
|
|
130
|
-
2,
|
|
130
|
+
2,848 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,45 @@
|
|
|
1
|
+
import type { AttributionAxes, AttributionAxisTag, AttributionEnvelope, ComputeAxisItem, DataAxisItem, GovernanceAxisEntry, ProtocolAxisItem } from './types.js';
|
|
2
|
+
/** Format a numeric weight or decimal-string input as the canonical
|
|
3
|
+
* 6-digit-after-point decimal string required by §2.5. Accepts numbers in
|
|
4
|
+
* [0, 1] or already-canonical strings. */
|
|
5
|
+
export declare function toWeightString(value: number | string): string;
|
|
6
|
+
/** Reject timestamps that a lenient parser would accept but §2.5 forbids.
|
|
7
|
+
* Forces ISO-8601 UTC with millisecond precision and literal Z suffix. */
|
|
8
|
+
export declare function assertCanonicalTimestamp(ts: string): void;
|
|
9
|
+
/** Produce the canonical timestamp for "now" or a supplied Date. Spec §2.5
|
|
10
|
+
* rejects `+00:00` and drops sub-ms precision; toISOString() already emits
|
|
11
|
+
* the required shape. */
|
|
12
|
+
export declare function canonicalTimestamp(now?: Date): string;
|
|
13
|
+
/** Sort an axis to §2.5 ordering so distinct orderings of the same logical
|
|
14
|
+
* content produce byte-identical canonicalizations.
|
|
15
|
+
*
|
|
16
|
+
* D: lexicographic by source_did.
|
|
17
|
+
* P: lexicographic by module_id + '\u0000' + module_version.
|
|
18
|
+
* C: lexicographic by provider_did.
|
|
19
|
+
* G: preserved as-is (root-to-leaf by depth).
|
|
20
|
+
*
|
|
21
|
+
* Residual buckets always sort to the end of their axis so their fixed
|
|
22
|
+
* identifier does not collide with DID ordering. At most one residual is
|
|
23
|
+
* permitted per axis; duplicates throw. */
|
|
24
|
+
export declare function sortDataAxis(items: DataAxisItem[]): DataAxisItem[];
|
|
25
|
+
export declare function sortProtocolAxis(items: ProtocolAxisItem[]): ProtocolAxisItem[];
|
|
26
|
+
export declare function sortComputeAxis(items: ComputeAxisItem[]): ComputeAxisItem[];
|
|
27
|
+
/** Governance axis is ordered by increasing depth (root principal first).
|
|
28
|
+
* Duplicate depths within the same chain are rejected. */
|
|
29
|
+
export declare function orderGovernanceAxis(items: GovernanceAxisEntry[]): GovernanceAxisEntry[];
|
|
30
|
+
/** Normalize all four axes to their canonical ordering. Callers can hand us
|
|
31
|
+
* unsorted input; the primitive never emits unsorted canonical bytes. */
|
|
32
|
+
export declare function normalizeAxes(axes: AttributionAxes): AttributionAxes;
|
|
33
|
+
/** SHA-256(canonical(axis_content)) as raw 32 bytes. §2.1. */
|
|
34
|
+
export declare function hashAxisLeaf(axis: unknown): Buffer;
|
|
35
|
+
/** Internal Merkle node: SHA-256(left_bytes || right_bytes). §2.1. */
|
|
36
|
+
export declare function hashNode(left: Buffer, right: Buffer): Buffer;
|
|
37
|
+
/** Hex sha256 of canonicalize(envelope). Used for signing and for deriving
|
|
38
|
+
* action_ref from the action tuple. */
|
|
39
|
+
export declare function canonicalHashHex(obj: unknown): string;
|
|
40
|
+
/** The canonical envelope §2.3 that Ed25519 signs. Returned as a string so
|
|
41
|
+
* Python and TypeScript sign/verify exactly the same bytes. */
|
|
42
|
+
export declare function envelopeBytes(env: AttributionEnvelope): string;
|
|
43
|
+
/** Type-safe enumeration of axis tags, for iteration. */
|
|
44
|
+
export declare const ATTRIBUTION_AXIS_TAGS: ReadonlyArray<AttributionAxisTag>;
|
|
45
|
+
//# sourceMappingURL=canonical.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../../../../src/v2/attribution-primitive/canonical.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAEjB,MAAM,YAAY,CAAA;AAKnB;;2CAE2C;AAC3C,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAgB7D;AAED;2EAC2E;AAC3E,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAMzD;AAED;;0BAE0B;AAC1B,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,IAAiB,GAAG,MAAM,CAIjE;AAYD;;;;;;;;;;4CAU4C;AAC5C,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,YAAY,EAAE,CAQlE;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,gBAAgB,EAAE,CAY9E;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE,CAU3E;AAED;2DAC2D;AAC3D,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,EAAE,CAUvF;AAED;0EAC0E;AAC1E,wBAAgB,aAAa,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe,CAOpE;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAElD;AAED,sEAAsE;AACtE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;wCACwC;AACxC,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAErD;AAED;gEACgE;AAChE,wBAAgB,aAAa,CAAC,GAAG,EAAE,mBAAmB,GAAG,MAAM,CAQ9D;AAED,yDAAyD;AACzD,eAAO,MAAM,qBAAqB,EAAE,aAAa,CAAC,kBAAkB,CAAwB,CAAA"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Copyright 2024-2026 Tymofii Pidlisnyi. Apache-2.0 license. See LICENSE.
|
|
2
|
+
// ══════════════════════════════════════════════════════════════════
|
|
3
|
+
// Attribution Primitive — canonicalization, ordering, numeric format
|
|
4
|
+
// ══════════════════════════════════════════════════════════════════
|
|
5
|
+
// Spec §2.5 specifies stricter canonicalization than RFC 8785. This file
|
|
6
|
+
// owns the additional constraints so A1 (canonicalization injectivity,
|
|
7
|
+
// §3.4) holds for schema-valid inputs.
|
|
8
|
+
// ══════════════════════════════════════════════════════════════════
|
|
9
|
+
import { createHash } from 'node:crypto';
|
|
10
|
+
import { canonicalize } from '../../core/canonical.js';
|
|
11
|
+
const WEIGHT_PATTERN = /^\d+\.\d{6}$/;
|
|
12
|
+
const ISO_8601_MS_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
13
|
+
/** Format a numeric weight or decimal-string input as the canonical
|
|
14
|
+
* 6-digit-after-point decimal string required by §2.5. Accepts numbers in
|
|
15
|
+
* [0, 1] or already-canonical strings. */
|
|
16
|
+
export function toWeightString(value) {
|
|
17
|
+
if (typeof value === 'string') {
|
|
18
|
+
if (!WEIGHT_PATTERN.test(value)) {
|
|
19
|
+
throw new Error(`attribution-primitive: weight string "${value}" must match /^\\d+\\.\\d{6}$/ (§2.5)`);
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
if (!Number.isFinite(value)) {
|
|
24
|
+
throw new Error(`attribution-primitive: weight must be finite, got ${value}`);
|
|
25
|
+
}
|
|
26
|
+
if (value < 0 || value > 1) {
|
|
27
|
+
throw new Error(`attribution-primitive: weight must be in [0, 1], got ${value}`);
|
|
28
|
+
}
|
|
29
|
+
return value.toFixed(6);
|
|
30
|
+
}
|
|
31
|
+
/** Reject timestamps that a lenient parser would accept but §2.5 forbids.
|
|
32
|
+
* Forces ISO-8601 UTC with millisecond precision and literal Z suffix. */
|
|
33
|
+
export function assertCanonicalTimestamp(ts) {
|
|
34
|
+
if (!ISO_8601_MS_PATTERN.test(ts)) {
|
|
35
|
+
throw new Error(`attribution-primitive: timestamp "${ts}" must be ISO-8601 UTC with millisecond precision and trailing Z (§2.5)`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Produce the canonical timestamp for "now" or a supplied Date. Spec §2.5
|
|
39
|
+
* rejects `+00:00` and drops sub-ms precision; toISOString() already emits
|
|
40
|
+
* the required shape. */
|
|
41
|
+
export function canonicalTimestamp(now = new Date()) {
|
|
42
|
+
const s = now.toISOString();
|
|
43
|
+
assertCanonicalTimestamp(s);
|
|
44
|
+
return s;
|
|
45
|
+
}
|
|
46
|
+
function isResidual(x) {
|
|
47
|
+
return (typeof x === 'object' &&
|
|
48
|
+
x !== null &&
|
|
49
|
+
'residual_id' in x &&
|
|
50
|
+
typeof x.residual_id === 'string' &&
|
|
51
|
+
x.residual_id.startsWith('residual:'));
|
|
52
|
+
}
|
|
53
|
+
/** Sort an axis to §2.5 ordering so distinct orderings of the same logical
|
|
54
|
+
* content produce byte-identical canonicalizations.
|
|
55
|
+
*
|
|
56
|
+
* D: lexicographic by source_did.
|
|
57
|
+
* P: lexicographic by module_id + '\u0000' + module_version.
|
|
58
|
+
* C: lexicographic by provider_did.
|
|
59
|
+
* G: preserved as-is (root-to-leaf by depth).
|
|
60
|
+
*
|
|
61
|
+
* Residual buckets always sort to the end of their axis so their fixed
|
|
62
|
+
* identifier does not collide with DID ordering. At most one residual is
|
|
63
|
+
* permitted per axis; duplicates throw. */
|
|
64
|
+
export function sortDataAxis(items) {
|
|
65
|
+
const residuals = items.filter(isResidual);
|
|
66
|
+
if (residuals.length > 1) {
|
|
67
|
+
throw new Error('attribution-primitive: at most one residual bucket permitted in axis D');
|
|
68
|
+
}
|
|
69
|
+
const explicit = items.filter((x) => !isResidual(x));
|
|
70
|
+
explicit.sort((a, b) => (a.source_did < b.source_did ? -1 : a.source_did > b.source_did ? 1 : 0));
|
|
71
|
+
return [...explicit, ...residuals];
|
|
72
|
+
}
|
|
73
|
+
export function sortProtocolAxis(items) {
|
|
74
|
+
const residuals = items.filter(isResidual);
|
|
75
|
+
if (residuals.length > 1) {
|
|
76
|
+
throw new Error('attribution-primitive: at most one residual bucket permitted in axis P');
|
|
77
|
+
}
|
|
78
|
+
const explicit = items.filter((x) => !isResidual(x));
|
|
79
|
+
explicit.sort((a, b) => {
|
|
80
|
+
const ka = `${a.module_id}\u0000${a.module_version}`;
|
|
81
|
+
const kb = `${b.module_id}\u0000${b.module_version}`;
|
|
82
|
+
return ka < kb ? -1 : ka > kb ? 1 : 0;
|
|
83
|
+
});
|
|
84
|
+
return [...explicit, ...residuals];
|
|
85
|
+
}
|
|
86
|
+
export function sortComputeAxis(items) {
|
|
87
|
+
const residuals = items.filter(isResidual);
|
|
88
|
+
if (residuals.length > 1) {
|
|
89
|
+
throw new Error('attribution-primitive: at most one residual bucket permitted in axis C');
|
|
90
|
+
}
|
|
91
|
+
const explicit = items.filter((x) => !isResidual(x));
|
|
92
|
+
explicit.sort((a, b) => a.provider_did < b.provider_did ? -1 : a.provider_did > b.provider_did ? 1 : 0);
|
|
93
|
+
return [...explicit, ...residuals];
|
|
94
|
+
}
|
|
95
|
+
/** Governance axis is ordered by increasing depth (root principal first).
|
|
96
|
+
* Duplicate depths within the same chain are rejected. */
|
|
97
|
+
export function orderGovernanceAxis(items) {
|
|
98
|
+
const ordered = [...items].sort((a, b) => a.depth - b.depth);
|
|
99
|
+
for (let i = 1; i < ordered.length; i++) {
|
|
100
|
+
if (ordered[i].depth === ordered[i - 1].depth) {
|
|
101
|
+
throw new Error(`attribution-primitive: governance axis has duplicate depth ${ordered[i].depth}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return ordered;
|
|
105
|
+
}
|
|
106
|
+
/** Normalize all four axes to their canonical ordering. Callers can hand us
|
|
107
|
+
* unsorted input; the primitive never emits unsorted canonical bytes. */
|
|
108
|
+
export function normalizeAxes(axes) {
|
|
109
|
+
return {
|
|
110
|
+
D: sortDataAxis(axes.D),
|
|
111
|
+
P: sortProtocolAxis(axes.P),
|
|
112
|
+
G: orderGovernanceAxis(axes.G),
|
|
113
|
+
C: sortComputeAxis(axes.C),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/** SHA-256(canonical(axis_content)) as raw 32 bytes. §2.1. */
|
|
117
|
+
export function hashAxisLeaf(axis) {
|
|
118
|
+
return createHash('sha256').update(canonicalize(axis)).digest();
|
|
119
|
+
}
|
|
120
|
+
/** Internal Merkle node: SHA-256(left_bytes || right_bytes). §2.1. */
|
|
121
|
+
export function hashNode(left, right) {
|
|
122
|
+
return createHash('sha256').update(Buffer.concat([left, right])).digest();
|
|
123
|
+
}
|
|
124
|
+
/** Hex sha256 of canonicalize(envelope). Used for signing and for deriving
|
|
125
|
+
* action_ref from the action tuple. */
|
|
126
|
+
export function canonicalHashHex(obj) {
|
|
127
|
+
return createHash('sha256').update(canonicalize(obj)).digest('hex');
|
|
128
|
+
}
|
|
129
|
+
/** The canonical envelope §2.3 that Ed25519 signs. Returned as a string so
|
|
130
|
+
* Python and TypeScript sign/verify exactly the same bytes. */
|
|
131
|
+
export function envelopeBytes(env) {
|
|
132
|
+
assertCanonicalTimestamp(env.timestamp);
|
|
133
|
+
return canonicalize({
|
|
134
|
+
action_ref: env.action_ref,
|
|
135
|
+
merkle_root: env.merkle_root,
|
|
136
|
+
issuer: env.issuer,
|
|
137
|
+
timestamp: env.timestamp,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/** Type-safe enumeration of axis tags, for iteration. */
|
|
141
|
+
export const ATTRIBUTION_AXIS_TAGS = ['D', 'P', 'G', 'C'];
|
|
142
|
+
//# sourceMappingURL=canonical.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../../../../src/v2/attribution-primitive/canonical.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AttributionAction, AttributionAxes, AttributionPrimitive } from './types.js';
|
|
2
|
+
/** Derive action_ref from the action tuple. §1.2 / §3.4.
|
|
3
|
+
*
|
|
4
|
+
* The spec pseudocode in §2.7 uses string concatenation (`agentId || type
|
|
5
|
+
* || canonical(params) || nonce`), but Theorem 1's reduction relies on
|
|
6
|
+
* canonical(T) being injective (A1). Plain string concatenation is not
|
|
7
|
+
* self-delimiting, so two distinct tuples could produce the same byte
|
|
8
|
+
* string. We adopt canonical(T) on the full tuple, which is injective by
|
|
9
|
+
* construction and matches the security argument. */
|
|
10
|
+
export declare function computeAttributionActionRef(action: AttributionAction): string;
|
|
11
|
+
export interface ConstructAttributionParams {
|
|
12
|
+
/** The action being attested. Used to derive action_ref. */
|
|
13
|
+
action: AttributionAction;
|
|
14
|
+
/** The four axes with their entries. Unsorted is fine — canonicalization
|
|
15
|
+
* will order them. */
|
|
16
|
+
axes: AttributionAxes;
|
|
17
|
+
/** Issuer DID of the gateway or agent producing the receipt. */
|
|
18
|
+
issuer: string;
|
|
19
|
+
/** Ed25519 private key (hex) that signs the envelope. Must match the
|
|
20
|
+
* public key registered for `issuer` out-of-band. */
|
|
21
|
+
issuerPrivateKey: string;
|
|
22
|
+
/** Override the timestamp (test fixtures, replayed audits). Must satisfy
|
|
23
|
+
* §2.5 — millisecond precision, trailing Z. Defaults to now(). */
|
|
24
|
+
timestamp?: string;
|
|
25
|
+
}
|
|
26
|
+
/** Build and sign a complete AttributionPrimitive. §2.7. */
|
|
27
|
+
export declare function constructAttributionPrimitive(params: ConstructAttributionParams): AttributionPrimitive;
|
|
28
|
+
/** Re-sign a primitive whose axes or metadata have changed (e.g., after
|
|
29
|
+
* applying decay in axis P). Returns a fresh primitive; the input is not
|
|
30
|
+
* mutated. Caller is responsible for providing a new timestamp if the
|
|
31
|
+
* resigned receipt should be distinct under replay protection. */
|
|
32
|
+
export declare function resignAttributionPrimitive(primitive: AttributionPrimitive, issuerPrivateKey: string, opts?: {
|
|
33
|
+
timestamp?: string;
|
|
34
|
+
axes?: AttributionAxes;
|
|
35
|
+
action?: AttributionAction;
|
|
36
|
+
}): AttributionPrimitive;
|
|
37
|
+
//# sourceMappingURL=construct.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"construct.d.ts","sourceRoot":"","sources":["../../../../src/v2/attribution-primitive/construct.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACrB,MAAM,YAAY,CAAA;AAEnB;;;;;;;sDAOsD;AACtD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAa7E;AAED,MAAM,WAAW,0BAA0B;IACzC,4DAA4D;IAC5D,MAAM,EAAE,iBAAiB,CAAA;IACzB;2BACuB;IACvB,IAAI,EAAE,eAAe,CAAA;IACrB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAA;IACd;0DACsD;IACtD,gBAAgB,EAAE,MAAM,CAAA;IACxB;uEACmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,4DAA4D;AAC5D,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,0BAA0B,GACjC,oBAAoB,CA0BtB;AAED;;;mEAGmE;AACnE,wBAAgB,0BAA0B,CACxC,SAAS,EAAE,oBAAoB,EAC/B,gBAAgB,EAAE,MAAM,EACxB,IAAI,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,eAAe,CAAC;IAAC,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAAE,GAChF,oBAAoB,CAiBtB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Copyright 2024-2026 Tymofii Pidlisnyi. Apache-2.0 license. See LICENSE.
|
|
2
|
+
// ══════════════════════════════════════════════════════════════════
|
|
3
|
+
// Attribution Primitive — construction
|
|
4
|
+
// ══════════════════════════════════════════════════════════════════
|
|
5
|
+
// Spec §2.7 composition pipeline. Given a set of axes, an issuer DID, and
|
|
6
|
+
// an action tuple, produce a signed primitive. Callers hand us already-
|
|
7
|
+
// computed axis entries; weight derivation and hash computation of the
|
|
8
|
+
// underlying per-axis artifacts (AccessReceipt hashes, evaluation receipt
|
|
9
|
+
// hashes, delegation scope hashes, attestation hashes) is deployment
|
|
10
|
+
// policy per §7.1.
|
|
11
|
+
// ══════════════════════════════════════════════════════════════════
|
|
12
|
+
import { sign } from '../../crypto/keys.js';
|
|
13
|
+
import { assertCanonicalTimestamp, canonicalHashHex, canonicalTimestamp, envelopeBytes, } from './canonical.js';
|
|
14
|
+
import { buildMerkleFrame } from './merkle.js';
|
|
15
|
+
/** Derive action_ref from the action tuple. §1.2 / §3.4.
|
|
16
|
+
*
|
|
17
|
+
* The spec pseudocode in §2.7 uses string concatenation (`agentId || type
|
|
18
|
+
* || canonical(params) || nonce`), but Theorem 1's reduction relies on
|
|
19
|
+
* canonical(T) being injective (A1). Plain string concatenation is not
|
|
20
|
+
* self-delimiting, so two distinct tuples could produce the same byte
|
|
21
|
+
* string. We adopt canonical(T) on the full tuple, which is injective by
|
|
22
|
+
* construction and matches the security argument. */
|
|
23
|
+
export function computeAttributionActionRef(action) {
|
|
24
|
+
if (!action.agentId)
|
|
25
|
+
throw new Error('attribution-primitive: action.agentId required');
|
|
26
|
+
if (!action.actionType)
|
|
27
|
+
throw new Error('attribution-primitive: action.actionType required');
|
|
28
|
+
if (!action.nonce)
|
|
29
|
+
throw new Error('attribution-primitive: action.nonce required');
|
|
30
|
+
if (typeof action.params !== 'object' || action.params === null) {
|
|
31
|
+
throw new Error('attribution-primitive: action.params must be an object');
|
|
32
|
+
}
|
|
33
|
+
return canonicalHashHex({
|
|
34
|
+
agentId: action.agentId,
|
|
35
|
+
actionType: action.actionType,
|
|
36
|
+
params: action.params,
|
|
37
|
+
nonce: action.nonce,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/** Build and sign a complete AttributionPrimitive. §2.7. */
|
|
41
|
+
export function constructAttributionPrimitive(params) {
|
|
42
|
+
if (!params.issuer)
|
|
43
|
+
throw new Error('attribution-primitive: issuer required');
|
|
44
|
+
if (!params.issuerPrivateKey)
|
|
45
|
+
throw new Error('attribution-primitive: issuerPrivateKey required');
|
|
46
|
+
const action_ref = computeAttributionActionRef(params.action);
|
|
47
|
+
const frame = buildMerkleFrame(params.axes);
|
|
48
|
+
const merkle_root = frame.root.toString('hex');
|
|
49
|
+
const timestamp = params.timestamp ?? canonicalTimestamp();
|
|
50
|
+
assertCanonicalTimestamp(timestamp);
|
|
51
|
+
const envelope = envelopeBytes({
|
|
52
|
+
action_ref,
|
|
53
|
+
merkle_root,
|
|
54
|
+
issuer: params.issuer,
|
|
55
|
+
timestamp,
|
|
56
|
+
});
|
|
57
|
+
const signature = sign(envelope, params.issuerPrivateKey);
|
|
58
|
+
return {
|
|
59
|
+
action_ref,
|
|
60
|
+
axes: frame.axes,
|
|
61
|
+
merkle_root,
|
|
62
|
+
issuer: params.issuer,
|
|
63
|
+
timestamp,
|
|
64
|
+
signature,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Re-sign a primitive whose axes or metadata have changed (e.g., after
|
|
68
|
+
* applying decay in axis P). Returns a fresh primitive; the input is not
|
|
69
|
+
* mutated. Caller is responsible for providing a new timestamp if the
|
|
70
|
+
* resigned receipt should be distinct under replay protection. */
|
|
71
|
+
export function resignAttributionPrimitive(primitive, issuerPrivateKey, opts) {
|
|
72
|
+
const axes = opts?.axes ?? primitive.axes;
|
|
73
|
+
const action_ref = opts?.action
|
|
74
|
+
? computeAttributionActionRef(opts.action)
|
|
75
|
+
: primitive.action_ref;
|
|
76
|
+
const frame = buildMerkleFrame(axes);
|
|
77
|
+
const merkle_root = frame.root.toString('hex');
|
|
78
|
+
const timestamp = opts?.timestamp ?? canonicalTimestamp();
|
|
79
|
+
assertCanonicalTimestamp(timestamp);
|
|
80
|
+
const envelope = envelopeBytes({
|
|
81
|
+
action_ref,
|
|
82
|
+
merkle_root,
|
|
83
|
+
issuer: primitive.issuer,
|
|
84
|
+
timestamp,
|
|
85
|
+
});
|
|
86
|
+
const signature = sign(envelope, issuerPrivateKey);
|
|
87
|
+
return { action_ref, axes: frame.axes, merkle_root, issuer: primitive.issuer, timestamp, signature };
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=construct.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"construct.js","sourceRoot":"","sources":["../../../../src/v2/attribution-primitive/construct.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type { AttributionAxisTag, AttributionAction, AttributionAxes, AttributionEnvelope, AttributionPrimitive, AttributionProjection, AttributionVerifyResult, AttributionConsistencyResult, DataAxisEntry, DataAxisItem, ProtocolAxisEntry, ProtocolAxisItem, GovernanceAxisEntry, ComputeAxisEntry, ComputeAxisItem, ResidualBucket, } from './types.js';
|
|
2
|
+
export { ATTRIBUTION_AXIS_TAGS, assertCanonicalTimestamp, canonicalTimestamp, canonicalHashHex, envelopeBytes, hashAxisLeaf, hashNode, normalizeAxes, orderGovernanceAxis, sortComputeAxis, sortDataAxis, sortProtocolAxis, toWeightString, } from './canonical.js';
|
|
3
|
+
export { buildMerkleFrame, projectionPath, reconstructRoot } from './merkle.js';
|
|
4
|
+
export type { MerkleFrame } from './merkle.js';
|
|
5
|
+
export { computeAttributionActionRef, constructAttributionPrimitive, resignAttributionPrimitive, } from './construct.js';
|
|
6
|
+
export type { ConstructAttributionParams } from './construct.js';
|
|
7
|
+
export { projectAttribution, projectAllAxes, projectionDataAsC, projectionDataAsD, projectionDataAsG, projectionDataAsP, } from './project.js';
|
|
8
|
+
export { checkProjectionConsistency, verifyAttributionPrimitive, verifyAttributionProjection, } from './verify.js';
|
|
9
|
+
export { DEFAULT_MIN_WEIGHT, aggregateComputeAxis, aggregateDataAxis, aggregateProtocolAxis, } from './residual.js';
|
|
10
|
+
export type { AggregateOptions, AggregationResult } from './residual.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/v2/attribution-primitive/index.ts"],"names":[],"mappings":"AAOA,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,4BAA4B,EAC5B,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,cAAc,GACf,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC/E,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAE9C,OAAO,EACL,2BAA2B,EAC3B,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,gBAAgB,CAAA;AACvB,YAAY,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAA;AAEhE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Copyright 2024-2026 Tymofii Pidlisnyi. Apache-2.0 license. See LICENSE.
|
|
2
|
+
// Attribution Primitive — public surface.
|
|
3
|
+
//
|
|
4
|
+
// Spec: ATTRIBUTION-PRIMITIVE-v1.1.md. See README/paper for the structural
|
|
5
|
+
// motivation; this module is the protocol primitive only. Visualization,
|
|
6
|
+
// cross-tenant analytics, and batch settlement are gateway-side.
|
|
7
|
+
export { ATTRIBUTION_AXIS_TAGS, assertCanonicalTimestamp, canonicalTimestamp, canonicalHashHex, envelopeBytes, hashAxisLeaf, hashNode, normalizeAxes, orderGovernanceAxis, sortComputeAxis, sortDataAxis, sortProtocolAxis, toWeightString, } from './canonical.js';
|
|
8
|
+
export { buildMerkleFrame, projectionPath, reconstructRoot } from './merkle.js';
|
|
9
|
+
export { computeAttributionActionRef, constructAttributionPrimitive, resignAttributionPrimitive, } from './construct.js';
|
|
10
|
+
export { projectAttribution, projectAllAxes, projectionDataAsC, projectionDataAsD, projectionDataAsG, projectionDataAsP, } from './project.js';
|
|
11
|
+
export { checkProjectionConsistency, verifyAttributionPrimitive, verifyAttributionProjection, } from './verify.js';
|
|
12
|
+
export { DEFAULT_MIN_WEIGHT, aggregateComputeAxis, aggregateDataAxis, aggregateProtocolAxis, } from './residual.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/v2/attribution-primitive/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,0CAA0C;AAC1C,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,iEAAiE;AAqBjE,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,cAAc,GACf,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAG/E,OAAO,EACL,2BAA2B,EAC3B,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AttributionAxes, AttributionAxisTag } from './types.js';
|
|
2
|
+
export interface MerkleFrame {
|
|
3
|
+
/** Canonically-ordered axes used to derive the leaves. */
|
|
4
|
+
axes: AttributionAxes;
|
|
5
|
+
leaves: {
|
|
6
|
+
D: Buffer;
|
|
7
|
+
P: Buffer;
|
|
8
|
+
G: Buffer;
|
|
9
|
+
C: Buffer;
|
|
10
|
+
};
|
|
11
|
+
nodes: {
|
|
12
|
+
N_content: Buffer;
|
|
13
|
+
N_auth_infra: Buffer;
|
|
14
|
+
};
|
|
15
|
+
root: Buffer;
|
|
16
|
+
}
|
|
17
|
+
/** Build the full tree for a set of axes. Callers pass the raw (possibly
|
|
18
|
+
* unsorted) axes; we normalize before hashing so the caller can't produce
|
|
19
|
+
* two different canonical representations of the same logical content. */
|
|
20
|
+
export declare function buildMerkleFrame(rawAxes: AttributionAxes): MerkleFrame;
|
|
21
|
+
/** The sibling path for a projection, in the order §2.2 specifies:
|
|
22
|
+
* [sibling_leaf_within_pair_hex, sibling_internal_node_hex]. */
|
|
23
|
+
export declare function projectionPath(frame: MerkleFrame, axis: AttributionAxisTag): [string, string];
|
|
24
|
+
/** Reconstruct the root from an axis's canonical leaf hash and the two-hop
|
|
25
|
+
* sibling path. §2.3 algorithm. Returns raw bytes so callers can diff the
|
|
26
|
+
* buffers; hex comparison is lossy under case normalization. */
|
|
27
|
+
export declare function reconstructRoot(axisLeaf: Buffer, path: [string, string], axis: AttributionAxisTag): Buffer;
|
|
28
|
+
//# sourceMappingURL=merkle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merkle.d.ts","sourceRoot":"","sources":["../../../../src/v2/attribution-primitive/merkle.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAErE,MAAM,WAAW,WAAW;IAC1B,0DAA0D;IAC1D,IAAI,EAAE,eAAe,CAAA;IACrB,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACtD,KAAK,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAA;IAClD,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;2EAE2E;AAC3E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,WAAW,CAetE;AAED;iEACiE;AACjE,wBAAgB,cAAc,CAC5B,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,kBAAkB,GACvB,CAAC,MAAM,EAAE,MAAM,CAAC,CAelB;AAED;;iEAEiE;AACjE,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EACtB,IAAI,EAAE,kBAAkB,GACvB,MAAM,CA2BR"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Copyright 2024-2026 Tymofii Pidlisnyi. Apache-2.0 license. See LICENSE.
|
|
2
|
+
// ══════════════════════════════════════════════════════════════════
|
|
3
|
+
// Attribution Primitive — balanced four-leaf Merkle tree
|
|
4
|
+
// ══════════════════════════════════════════════════════════════════
|
|
5
|
+
// Spec §2.1: four leaves in fixed positions. Content pair (D, P) on the
|
|
6
|
+
// left, authority-infrastructure pair (G, C) on the right, balanced above.
|
|
7
|
+
// All projections share a path length of two.
|
|
8
|
+
// ══════════════════════════════════════════════════════════════════
|
|
9
|
+
import { hashAxisLeaf, hashNode, normalizeAxes } from './canonical.js';
|
|
10
|
+
/** Build the full tree for a set of axes. Callers pass the raw (possibly
|
|
11
|
+
* unsorted) axes; we normalize before hashing so the caller can't produce
|
|
12
|
+
* two different canonical representations of the same logical content. */
|
|
13
|
+
export function buildMerkleFrame(rawAxes) {
|
|
14
|
+
const axes = normalizeAxes(rawAxes);
|
|
15
|
+
const leafD = hashAxisLeaf(axes.D);
|
|
16
|
+
const leafP = hashAxisLeaf(axes.P);
|
|
17
|
+
const leafG = hashAxisLeaf(axes.G);
|
|
18
|
+
const leafC = hashAxisLeaf(axes.C);
|
|
19
|
+
const nContent = hashNode(leafD, leafP);
|
|
20
|
+
const nAuthInfra = hashNode(leafG, leafC);
|
|
21
|
+
const root = hashNode(nContent, nAuthInfra);
|
|
22
|
+
return {
|
|
23
|
+
axes,
|
|
24
|
+
leaves: { D: leafD, P: leafP, G: leafG, C: leafC },
|
|
25
|
+
nodes: { N_content: nContent, N_auth_infra: nAuthInfra },
|
|
26
|
+
root,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** The sibling path for a projection, in the order §2.2 specifies:
|
|
30
|
+
* [sibling_leaf_within_pair_hex, sibling_internal_node_hex]. */
|
|
31
|
+
export function projectionPath(frame, axis) {
|
|
32
|
+
switch (axis) {
|
|
33
|
+
case 'D':
|
|
34
|
+
return [frame.leaves.P.toString('hex'), frame.nodes.N_auth_infra.toString('hex')];
|
|
35
|
+
case 'P':
|
|
36
|
+
return [frame.leaves.D.toString('hex'), frame.nodes.N_auth_infra.toString('hex')];
|
|
37
|
+
case 'G':
|
|
38
|
+
return [frame.leaves.C.toString('hex'), frame.nodes.N_content.toString('hex')];
|
|
39
|
+
case 'C':
|
|
40
|
+
return [frame.leaves.G.toString('hex'), frame.nodes.N_content.toString('hex')];
|
|
41
|
+
default: {
|
|
42
|
+
const exhaustive = axis;
|
|
43
|
+
throw new Error(`attribution-primitive: unknown axis tag ${String(exhaustive)}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Reconstruct the root from an axis's canonical leaf hash and the two-hop
|
|
48
|
+
* sibling path. §2.3 algorithm. Returns raw bytes so callers can diff the
|
|
49
|
+
* buffers; hex comparison is lossy under case normalization. */
|
|
50
|
+
export function reconstructRoot(axisLeaf, path, axis) {
|
|
51
|
+
const sibling = Buffer.from(path[0], 'hex');
|
|
52
|
+
const siblingInternal = Buffer.from(path[1], 'hex');
|
|
53
|
+
if (sibling.length !== 32 || siblingInternal.length !== 32) {
|
|
54
|
+
throw new Error(`attribution-primitive: merkle path hashes must be 32-byte sha256 (got ${sibling.length}, ${siblingInternal.length})`);
|
|
55
|
+
}
|
|
56
|
+
let internal;
|
|
57
|
+
switch (axis) {
|
|
58
|
+
case 'D':
|
|
59
|
+
internal = hashNode(axisLeaf, sibling); // leaf_D || leaf_P
|
|
60
|
+
return hashNode(internal, siblingInternal); // N_content || N_auth_infra
|
|
61
|
+
case 'P':
|
|
62
|
+
internal = hashNode(sibling, axisLeaf); // leaf_D || leaf_P
|
|
63
|
+
return hashNode(internal, siblingInternal);
|
|
64
|
+
case 'G':
|
|
65
|
+
internal = hashNode(axisLeaf, sibling); // leaf_G || leaf_C
|
|
66
|
+
return hashNode(siblingInternal, internal); // N_content || N_auth_infra
|
|
67
|
+
case 'C':
|
|
68
|
+
internal = hashNode(sibling, axisLeaf); // leaf_G || leaf_C
|
|
69
|
+
return hashNode(siblingInternal, internal);
|
|
70
|
+
default: {
|
|
71
|
+
const exhaustive = axis;
|
|
72
|
+
throw new Error(`attribution-primitive: unknown axis tag ${String(exhaustive)}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=merkle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merkle.js","sourceRoot":"","sources":["../../../../src/v2/attribution-primitive/merkle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { AttributionAxisTag, AttributionPrimitive, AttributionProjection, ComputeAxisItem, DataAxisItem, GovernanceAxisEntry, ProtocolAxisItem } from './types.js';
|
|
2
|
+
/** Extract a single axis projection from a primitive. §2.2. The projection
|
|
3
|
+
* carries a copy of the axis content (no deep clone — callers treating
|
|
4
|
+
* projections as transport should serialize immediately) plus the two-hop
|
|
5
|
+
* sibling path to reconstruct the root. */
|
|
6
|
+
export declare function projectAttribution(primitive: AttributionPrimitive, axis: AttributionAxisTag): AttributionProjection;
|
|
7
|
+
/** Convenience: extract all four projections in one call. Useful when an
|
|
8
|
+
* issuer wants to emit projections to four independent settlement queues
|
|
9
|
+
* in parallel. */
|
|
10
|
+
export declare function projectAllAxes(primitive: AttributionPrimitive): {
|
|
11
|
+
D: AttributionProjection;
|
|
12
|
+
P: AttributionProjection;
|
|
13
|
+
G: AttributionProjection;
|
|
14
|
+
C: AttributionProjection;
|
|
15
|
+
};
|
|
16
|
+
/** Type-narrowing helpers so callers can pull a projection's axis_data with
|
|
17
|
+
* the right shape. Throws if the tag doesn't match the expected axis.
|
|
18
|
+
* (Verification happens separately in verify.ts — these helpers only do
|
|
19
|
+
* runtime-tag dispatch, no signature checking.) */
|
|
20
|
+
export declare function projectionDataAsD(p: AttributionProjection): DataAxisItem[];
|
|
21
|
+
export declare function projectionDataAsP(p: AttributionProjection): ProtocolAxisItem[];
|
|
22
|
+
export declare function projectionDataAsG(p: AttributionProjection): GovernanceAxisEntry[];
|
|
23
|
+
export declare function projectionDataAsC(p: AttributionProjection): ComputeAxisItem[];
|
|
24
|
+
//# sourceMappingURL=project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../../src/v2/attribution-primitive/project.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAEV,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAenB;;;4CAG4C;AAC5C,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,oBAAoB,EAC/B,IAAI,EAAE,kBAAkB,GACvB,qBAAqB,CAsBvB;AAED;;mBAEmB;AACnB,wBAAgB,cAAc,CAC5B,SAAS,EAAE,oBAAoB,GAC9B;IAAE,CAAC,EAAE,qBAAqB,CAAC;IAAC,CAAC,EAAE,qBAAqB,CAAC;IAAC,CAAC,EAAE,qBAAqB,CAAC;IAAC,CAAC,EAAE,qBAAqB,CAAA;CAAE,CAO5G;AAED;;;oDAGoD;AACpD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,qBAAqB,GAAG,YAAY,EAAE,CAG1E;AACD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,qBAAqB,GAAG,gBAAgB,EAAE,CAG9E;AACD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,qBAAqB,GAAG,mBAAmB,EAAE,CAGjF;AACD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,qBAAqB,GAAG,eAAe,EAAE,CAG7E"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// Copyright 2024-2026 Tymofii Pidlisnyi. Apache-2.0 license. See LICENSE.
|
|
2
|
+
// ══════════════════════════════════════════════════════════════════
|
|
3
|
+
// Attribution Primitive — axis projections
|
|
4
|
+
// ══════════════════════════════════════════════════════════════════
|
|
5
|
+
// Spec §2.2 / §2.3. Each projection extracts one axis's content plus the
|
|
6
|
+
// sibling-hash path needed to reconstruct the signed root. The other three
|
|
7
|
+
// axes' contents are not recoverable from a single projection (I3, §3.3).
|
|
8
|
+
// ══════════════════════════════════════════════════════════════════
|
|
9
|
+
import { normalizeAxes } from './canonical.js';
|
|
10
|
+
import { buildMerkleFrame, projectionPath } from './merkle.js';
|
|
11
|
+
function selectAxis(axes, axis) {
|
|
12
|
+
switch (axis) {
|
|
13
|
+
case 'D':
|
|
14
|
+
return axes.D;
|
|
15
|
+
case 'P':
|
|
16
|
+
return axes.P;
|
|
17
|
+
case 'G':
|
|
18
|
+
return axes.G;
|
|
19
|
+
case 'C':
|
|
20
|
+
return axes.C;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** Extract a single axis projection from a primitive. §2.2. The projection
|
|
24
|
+
* carries a copy of the axis content (no deep clone — callers treating
|
|
25
|
+
* projections as transport should serialize immediately) plus the two-hop
|
|
26
|
+
* sibling path to reconstruct the root. */
|
|
27
|
+
export function projectAttribution(primitive, axis) {
|
|
28
|
+
if (axis !== 'D' && axis !== 'P' && axis !== 'G' && axis !== 'C') {
|
|
29
|
+
throw new Error(`attribution-primitive: invalid axis tag "${String(axis)}"`);
|
|
30
|
+
}
|
|
31
|
+
// Re-normalize to guarantee the tree we build here matches whatever the
|
|
32
|
+
// original issuer produced. Primitive fields other than axes could have
|
|
33
|
+
// been tampered with after construction — we don't trust primitive inputs
|
|
34
|
+
// to be canonical on their own.
|
|
35
|
+
const normalized = normalizeAxes(primitive.axes);
|
|
36
|
+
const frame = buildMerkleFrame(normalized);
|
|
37
|
+
const path = projectionPath(frame, axis);
|
|
38
|
+
return {
|
|
39
|
+
action_ref: primitive.action_ref,
|
|
40
|
+
axis_tag: axis,
|
|
41
|
+
axis_data: selectAxis(frame.axes, axis),
|
|
42
|
+
merkle_path: path,
|
|
43
|
+
merkle_root: primitive.merkle_root,
|
|
44
|
+
issuer: primitive.issuer,
|
|
45
|
+
timestamp: primitive.timestamp,
|
|
46
|
+
signature: primitive.signature,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Convenience: extract all four projections in one call. Useful when an
|
|
50
|
+
* issuer wants to emit projections to four independent settlement queues
|
|
51
|
+
* in parallel. */
|
|
52
|
+
export function projectAllAxes(primitive) {
|
|
53
|
+
return {
|
|
54
|
+
D: projectAttribution(primitive, 'D'),
|
|
55
|
+
P: projectAttribution(primitive, 'P'),
|
|
56
|
+
G: projectAttribution(primitive, 'G'),
|
|
57
|
+
C: projectAttribution(primitive, 'C'),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Type-narrowing helpers so callers can pull a projection's axis_data with
|
|
61
|
+
* the right shape. Throws if the tag doesn't match the expected axis.
|
|
62
|
+
* (Verification happens separately in verify.ts — these helpers only do
|
|
63
|
+
* runtime-tag dispatch, no signature checking.) */
|
|
64
|
+
export function projectionDataAsD(p) {
|
|
65
|
+
if (p.axis_tag !== 'D')
|
|
66
|
+
throw new Error(`expected axis D projection, got ${p.axis_tag}`);
|
|
67
|
+
return p.axis_data;
|
|
68
|
+
}
|
|
69
|
+
export function projectionDataAsP(p) {
|
|
70
|
+
if (p.axis_tag !== 'P')
|
|
71
|
+
throw new Error(`expected axis P projection, got ${p.axis_tag}`);
|
|
72
|
+
return p.axis_data;
|
|
73
|
+
}
|
|
74
|
+
export function projectionDataAsG(p) {
|
|
75
|
+
if (p.axis_tag !== 'G')
|
|
76
|
+
throw new Error(`expected axis G projection, got ${p.axis_tag}`);
|
|
77
|
+
return p.axis_data;
|
|
78
|
+
}
|
|
79
|
+
export function projectionDataAsC(p) {
|
|
80
|
+
if (p.axis_tag !== 'C')
|
|
81
|
+
throw new Error(`expected axis C projection, got ${p.axis_tag}`);
|
|
82
|
+
return p.axis_data;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=project.js.map
|