@fide.work/fcp 0.0.1-alpha.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.
Files changed (78) hide show
  1. package/README.md +18 -0
  2. package/dist/attestation/create.d.ts +173 -0
  3. package/dist/attestation/create.js +179 -0
  4. package/dist/attestation/index.d.ts +7 -0
  5. package/dist/attestation/index.js +7 -0
  6. package/dist/attestation/verify.d.ts +56 -0
  7. package/dist/attestation/verify.js +94 -0
  8. package/dist/broadcasting/config.d.ts +27 -0
  9. package/dist/broadcasting/config.js +22 -0
  10. package/dist/broadcasting/index.d.ts +7 -0
  11. package/dist/broadcasting/index.js +7 -0
  12. package/dist/broadcasting/registry.d.ts +111 -0
  13. package/dist/broadcasting/registry.js +99 -0
  14. package/dist/experimental/attestation/create.d.ts +173 -0
  15. package/dist/experimental/attestation/create.js +188 -0
  16. package/dist/experimental/attestation/index.d.ts +7 -0
  17. package/dist/experimental/attestation/index.js +7 -0
  18. package/dist/experimental/attestation/verify.d.ts +56 -0
  19. package/dist/experimental/attestation/verify.js +94 -0
  20. package/dist/experimental/broadcasting/config.d.ts +27 -0
  21. package/dist/experimental/broadcasting/config.js +22 -0
  22. package/dist/experimental/broadcasting/index.d.ts +7 -0
  23. package/dist/experimental/broadcasting/index.js +7 -0
  24. package/dist/experimental/broadcasting/registry.d.ts +111 -0
  25. package/dist/experimental/broadcasting/registry.js +99 -0
  26. package/dist/experimental/index.d.ts +9 -0
  27. package/dist/experimental/index.js +13 -0
  28. package/dist/experimental/merkle/index.d.ts +6 -0
  29. package/dist/experimental/merkle/index.js +6 -0
  30. package/dist/experimental/merkle/tree.d.ts +72 -0
  31. package/dist/experimental/merkle/tree.js +154 -0
  32. package/dist/experimental/signing/ed25519.d.ts +116 -0
  33. package/dist/experimental/signing/ed25519.js +161 -0
  34. package/dist/experimental/signing/eip191.d.ts +50 -0
  35. package/dist/experimental/signing/eip191.js +96 -0
  36. package/dist/experimental/signing/eip712.d.ts +112 -0
  37. package/dist/experimental/signing/eip712.js +187 -0
  38. package/dist/experimental/signing/index.d.ts +8 -0
  39. package/dist/experimental/signing/index.js +11 -0
  40. package/dist/fide-id/calculateFideId.d.ts +21 -0
  41. package/dist/fide-id/calculateFideId.js +53 -0
  42. package/dist/fide-id/calculateStatementFideId.d.ts +21 -0
  43. package/dist/fide-id/calculateStatementFideId.js +38 -0
  44. package/dist/fide-id/constants.d.ts +43 -0
  45. package/dist/fide-id/constants.js +55 -0
  46. package/dist/fide-id/index.d.ts +10 -0
  47. package/dist/fide-id/index.js +12 -0
  48. package/dist/fide-id/types.d.ts +52 -0
  49. package/dist/fide-id/types.js +5 -0
  50. package/dist/fide-id/utils.d.ts +30 -0
  51. package/dist/fide-id/utils.js +65 -0
  52. package/dist/index.d.ts +11 -0
  53. package/dist/index.js +19 -0
  54. package/dist/merkle/index.d.ts +6 -0
  55. package/dist/merkle/index.js +6 -0
  56. package/dist/merkle/tree.d.ts +72 -0
  57. package/dist/merkle/tree.js +154 -0
  58. package/dist/schema/evaluations.d.ts +31 -0
  59. package/dist/schema/evaluations.js +31 -0
  60. package/dist/schema/index.d.ts +6 -0
  61. package/dist/schema/index.js +6 -0
  62. package/dist/schema/predicates.d.ts +110 -0
  63. package/dist/schema/predicates.js +122 -0
  64. package/dist/signing/ed25519.d.ts +116 -0
  65. package/dist/signing/ed25519.js +161 -0
  66. package/dist/signing/eip191.d.ts +50 -0
  67. package/dist/signing/eip191.js +96 -0
  68. package/dist/signing/eip712.d.ts +112 -0
  69. package/dist/signing/eip712.js +187 -0
  70. package/dist/signing/index.d.ts +8 -0
  71. package/dist/signing/index.js +11 -0
  72. package/dist/statement/build.d.ts +99 -0
  73. package/dist/statement/build.js +71 -0
  74. package/dist/statement/index.d.ts +6 -0
  75. package/dist/statement/index.js +6 -0
  76. package/dist/statement/policy.d.ts +33 -0
  77. package/dist/statement/policy.js +183 -0
  78. package/package.json +64 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * FCP SDK Broadcasting Utilities
3
+ *
4
+ * Helpers for formatting attestations for JSONL registry files.
5
+ *
6
+ * Note: This module provides formatting helpers. Actual Git operations
7
+ * (commit, push) should be handled by your application using libraries
8
+ * like `simple-git` or `isomorphic-git`.
9
+ */
10
+ import type { AttestationResult } from "../attestation/index.js";
11
+ import type { Statement } from "../statement/build.js";
12
+ /**
13
+ * Statement object in lean JSONL format
14
+ * Uses short keys for efficiency: s/sr, p/pr, o/or
15
+ */
16
+ export interface JSONLStatement {
17
+ /** Subject Fide ID (full did:fide:0x... format) */
18
+ s: string;
19
+ /** Subject raw identifier */
20
+ sr: string;
21
+ /** Predicate Fide ID (full did:fide:0x... format) */
22
+ p: string;
23
+ /** Predicate raw identifier */
24
+ pr: string;
25
+ /** Object Fide ID (full did:fide:0x... format) */
26
+ o: string;
27
+ /** Object raw identifier */
28
+ or: string;
29
+ }
30
+ /**
31
+ * Lean attestation format for JSONL registry files
32
+ *
33
+ * Optimized for indexers: minimal verbosity, all data needed for verification
34
+ * and materialization. Each line is one attestation batch.
35
+ *
36
+ * Format matches canonical attestation data structure: {m, r, s, u}
37
+ * Indexer derives attestation Fide ID from these fields.
38
+ */
39
+ export interface JSONLAttestation {
40
+ /** Method: Signing method (e.g., "ed25519", "eip712", "eip191") */
41
+ m: string;
42
+ /** User: CAIP-10 signer identifier */
43
+ u: string;
44
+ /** Root: Merkle root commitment */
45
+ r: string;
46
+ /** Signature: Cryptographic signature */
47
+ s: string;
48
+ /** Timestamp: ISO 8601 UTC timestamp */
49
+ t: string;
50
+ /** Data: Array of statements in this batch */
51
+ d: JSONLStatement[];
52
+ }
53
+ /**
54
+ * Format an attestation result for JSONL output
55
+ *
56
+ * Converts an AttestationResult into the lean JSONL format optimized for indexers.
57
+ * Each line in the JSONL file should be one attestation batch (one signature covering
58
+ * multiple statements via Merkle root).
59
+ *
60
+ * Format uses short keys (m, u, r, s, t, d) matching the canonical attestation
61
+ * data structure. Indexer derives attestation Fide ID from {m, r, s, u}.
62
+ *
63
+ * @param attestationResult - The result from createAttestation
64
+ * @param statements - The original statements that were attested (must match statementFideIds order)
65
+ * @param signedAt - ISO timestamp when the attestation was signed (defaults to current time)
66
+ * @returns Formatted attestation ready for JSONL output
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * const statements = await buildStatementBatch([...]);
71
+ * const attestation = await createAttestation(statementFideIds, options);
72
+ * const jsonlAttestation = formatAttestationForJSONL(attestation, statements);
73
+ *
74
+ * // Write to JSONL file (one line per batch)
75
+ * fs.appendFileSync('attestation.jsonl', JSON.stringify(jsonlAttestation) + '\n');
76
+ * ```
77
+ */
78
+ export declare function formatAttestationForJSONL(attestationResult: AttestationResult, statements: Statement[], signedAt?: string): JSONLAttestation;
79
+ /**
80
+ * Generate the registry directory path for a given date
81
+ *
82
+ * Follows the YYYY/MM/DD structure required for Fide attestation registries.
83
+ * Uses UTC timezone for consistency across timezones.
84
+ *
85
+ * @param date - Date object (defaults to current UTC date)
86
+ * @returns Directory path (e.g., "2024/01/15")
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * const path = generateRegistryPath(new Date('2024-01-15T00:00:00Z'));
91
+ * // Result: "2024/01/15"
92
+ * ```
93
+ */
94
+ export declare function generateRegistryPath(date?: Date): string;
95
+ /**
96
+ * Generate a JSONL filename following the registry convention
97
+ *
98
+ * Format: YYYY-MM-DD-{HHmm}-{sequence}.jsonl
99
+ * Uses UTC timezone for consistency across timezones.
100
+ *
101
+ * @param date - Date object (defaults to current UTC date)
102
+ * @param sequence - Sequence number (defaults to 1)
103
+ * @returns Filename (e.g., "2024-01-15-1400-1.jsonl")
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * const filename = generateJSONLFilename(new Date('2024-01-15T14:00:00Z'), 1);
108
+ * // Result: "2024-01-15-1400-1.jsonl"
109
+ * ```
110
+ */
111
+ export declare function generateJSONLFilename(date?: Date, sequence?: number): string;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * FCP SDK Broadcasting Utilities
3
+ *
4
+ * Helpers for formatting attestations for JSONL registry files.
5
+ *
6
+ * Note: This module provides formatting helpers. Actual Git operations
7
+ * (commit, push) should be handled by your application using libraries
8
+ * like `simple-git` or `isomorphic-git`.
9
+ */
10
+ /**
11
+ * Format an attestation result for JSONL output
12
+ *
13
+ * Converts an AttestationResult into the lean JSONL format optimized for indexers.
14
+ * Each line in the JSONL file should be one attestation batch (one signature covering
15
+ * multiple statements via Merkle root).
16
+ *
17
+ * Format uses short keys (m, u, r, s, t, d) matching the canonical attestation
18
+ * data structure. Indexer derives attestation Fide ID from {m, r, s, u}.
19
+ *
20
+ * @param attestationResult - The result from createAttestation
21
+ * @param statements - The original statements that were attested (must match statementFideIds order)
22
+ * @param signedAt - ISO timestamp when the attestation was signed (defaults to current time)
23
+ * @returns Formatted attestation ready for JSONL output
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * const statements = await buildStatementBatch([...]);
28
+ * const attestation = await createAttestation(statementFideIds, options);
29
+ * const jsonlAttestation = formatAttestationForJSONL(attestation, statements);
30
+ *
31
+ * // Write to JSONL file (one line per batch)
32
+ * fs.appendFileSync('attestation.jsonl', JSON.stringify(jsonlAttestation) + '\n');
33
+ * ```
34
+ */
35
+ export function formatAttestationForJSONL(attestationResult, statements, signedAt = new Date().toISOString()) {
36
+ // Convert statements to lean JSONL format with short keys
37
+ const jsonlStatements = statements.map(stmt => ({
38
+ s: stmt.subjectFideId,
39
+ sr: stmt.subjectRawIdentifier,
40
+ p: stmt.predicateFideId,
41
+ pr: stmt.predicateRawIdentifier,
42
+ o: stmt.objectFideId,
43
+ or: stmt.objectRawIdentifier
44
+ }));
45
+ return {
46
+ m: attestationResult.attestationData.m,
47
+ u: attestationResult.attestationData.u,
48
+ r: attestationResult.merkleRoot,
49
+ s: attestationResult.attestationData.s,
50
+ t: signedAt,
51
+ d: jsonlStatements
52
+ };
53
+ }
54
+ /**
55
+ * Generate the registry directory path for a given date
56
+ *
57
+ * Follows the YYYY/MM/DD structure required for Fide attestation registries.
58
+ * Uses UTC timezone for consistency across timezones.
59
+ *
60
+ * @param date - Date object (defaults to current UTC date)
61
+ * @returns Directory path (e.g., "2024/01/15")
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * const path = generateRegistryPath(new Date('2024-01-15T00:00:00Z'));
66
+ * // Result: "2024/01/15"
67
+ * ```
68
+ */
69
+ export function generateRegistryPath(date = new Date()) {
70
+ const year = date.getUTCFullYear();
71
+ const month = String(date.getUTCMonth() + 1).padStart(2, '0');
72
+ const day = String(date.getUTCDate()).padStart(2, '0');
73
+ return `${year}/${month}/${day}`;
74
+ }
75
+ /**
76
+ * Generate a JSONL filename following the registry convention
77
+ *
78
+ * Format: YYYY-MM-DD-{HHmm}-{sequence}.jsonl
79
+ * Uses UTC timezone for consistency across timezones.
80
+ *
81
+ * @param date - Date object (defaults to current UTC date)
82
+ * @param sequence - Sequence number (defaults to 1)
83
+ * @returns Filename (e.g., "2024-01-15-1400-1.jsonl")
84
+ *
85
+ * @example
86
+ * ```ts
87
+ * const filename = generateJSONLFilename(new Date('2024-01-15T14:00:00Z'), 1);
88
+ * // Result: "2024-01-15-1400-1.jsonl"
89
+ * ```
90
+ */
91
+ export function generateJSONLFilename(date = new Date(), sequence = 1) {
92
+ const year = date.getUTCFullYear();
93
+ const month = String(date.getUTCMonth() + 1).padStart(2, '0');
94
+ const day = String(date.getUTCDate()).padStart(2, '0');
95
+ const hours = String(date.getUTCHours()).padStart(2, '0');
96
+ const minutes = String(date.getUTCMinutes()).padStart(2, '0');
97
+ const timeWindow = `${hours}${minutes}`;
98
+ return `${year}-${month}-${day}-${timeWindow}-${sequence}.jsonl`;
99
+ }
@@ -0,0 +1,173 @@
1
+ /**
2
+ * FCP SDK Attestation Utilities
3
+ *
4
+ * High-level helpers for creating and verifying attestations.
5
+ * Combines Fide ID calculation, Merkle trees, and signing.
6
+ */
7
+ import type { FideId } from "../../fide-id/types.js";
8
+ import { type MerkleProof } from "../merkle/index.js";
9
+ /**
10
+ * Signing method identifier
11
+ *
12
+ * `ed25519` has no external dependency.
13
+ * `eip712` and `eip191` require the optional `viem` peer dependency.
14
+ */
15
+ export type SigningMethod = 'ed25519' | 'eip712' | 'eip191';
16
+ /**
17
+ * Attestation data structure (baked into Fide ID)
18
+ * Uses short keys to match protocol: m, u, r, s
19
+ */
20
+ export interface AttestationData {
21
+ /** Method: Signing standard used */
22
+ m: SigningMethod;
23
+ /** User: CAIP-10 signer identifier */
24
+ u: string;
25
+ /** Root: Merkle tree commitment */
26
+ r: string;
27
+ /** Signature: Cryptographic proof */
28
+ s: string;
29
+ }
30
+ /**
31
+ * Full attestation result
32
+ */
33
+ export interface AttestationResult {
34
+ /** The Attestation Fide ID */
35
+ attestationFideId: FideId;
36
+ /** The raw attestation data */
37
+ attestationData: AttestationData;
38
+ /** The normalized JSON string (raw identifier) */
39
+ rawIdentifier: string;
40
+ /** The Merkle root */
41
+ merkleRoot: string;
42
+ /** Proofs for each statement, keyed by statement Fide ID */
43
+ proofs: Map<string, MerkleProof>;
44
+ }
45
+ /**
46
+ * Options for creating an attestation
47
+ */
48
+ export interface CreateAttestationOptions {
49
+ /** The signing method to use (`eip712`/`eip191` require `viem` to be installed). */
50
+ method: SigningMethod;
51
+ /** CAIP-10 identifier for the signer (e.g., "eip155:1:0x...") */
52
+ caip10User: string;
53
+ /** Signing function - takes merkle root string, returns signature hex string */
54
+ sign: (merkleRoot: string) => Promise<string>;
55
+ }
56
+ /**
57
+ * Provenance statement linking a statement to its attestation
58
+ */
59
+ export interface ProvenanceStatement {
60
+ subjectFideId: string;
61
+ predicateFideId: string;
62
+ objectFideId: string;
63
+ predicateRawIdentifier: string;
64
+ objectRawIdentifier: string;
65
+ }
66
+ /**
67
+ * Create an attestation for a batch of statement Fide IDs
68
+ *
69
+ * This function:
70
+ * 1. Builds a Merkle tree from the statement Fide IDs
71
+ * 2. Signs the Merkle root using the provided signing function
72
+ * 3. Creates the attestation data structure
73
+ * 4. Derives the Attestation Fide ID
74
+ *
75
+ * @param statementFideIds - Array of statement Fide IDs.
76
+ * @param options - Configuration options for operation.
77
+ * @paramDefault statementFideIds ["did:fide:0x10...", "did:fide:0x10..."]
78
+ * @paramDefault options {"method":"ed25519","caip10User":"ed25519:123...","sign":"async (root) => 'signature'"}
79
+ * @returns Full attestation result including ID, data, and proofs
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * import { createAttestation, signEd25519 } from '@fide.work/fcp';
84
+ *
85
+ * const result = await createAttestation(
86
+ * [statement1FideId, statement2FideId],
87
+ * {
88
+ * method: 'ed25519',
89
+ * caip10User: 'ed25519::abc123...',
90
+ * sign: (root) => signEd25519(root, privateKey)
91
+ * }
92
+ * );
93
+ *
94
+ * console.log('Attestation ID:', result.attestationFideId);
95
+ * ```
96
+ */
97
+ export declare function createAttestation(statementFideIds: string[], options: CreateAttestationOptions): Promise<AttestationResult>;
98
+ /**
99
+ * Create provenance statements linking each statement to the attestation
100
+ *
101
+ * These are the "Statement → prov:wasGeneratedBy → Attestation" triples
102
+ * that connect content statements to their attestation.
103
+ *
104
+ * @param statementFideIds - Array of statement Fide IDs to include in attestation
105
+ * @param attestationResult - The attestation data structure
106
+ * @returns Array of provenance statements to publish
107
+ *
108
+ * @example
109
+ * ```ts
110
+ * const provenance = await createProvenanceStatements(
111
+ * statementFideIds,
112
+ * attestationResult
113
+ * );
114
+ * // Each provenance statement links a content statement to the attestation
115
+ * ```
116
+ */
117
+ export declare function createProvenanceStatements(statementFideIds: string[], attestationResult: AttestationResult): Promise<ProvenanceStatement[]>;
118
+ /**
119
+ * Verify that a statement is part of an attestation
120
+ *
121
+ * This verifies the Merkle proof but does NOT verify the signature.
122
+ * Signature verification depends on the signing method and should
123
+ * be done separately using verifyEd25519 or verifyEip712.
124
+ *
125
+ * @param statementFideId - The leaf value to verify.
126
+ * @param proof - The Merkle proof path.
127
+ * @param attestationData - The attestation data.
128
+ * @paramDefault statementFideId did:fide:0x10...
129
+ * @paramDefault proof ["hash1", "hash2"]
130
+ * @paramDefault attestationData {"r":"root-hash"}
131
+ * @returns True if the statement is in the attestation
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * const isInBatch = await verifyStatementInAttestation(
136
+ * statementFideId,
137
+ * proof,
138
+ * attestationData
139
+ * );
140
+ * ```
141
+ */
142
+ export declare function verifyStatementInAttestation(statementFideId: string, proof: MerkleProof, attestationData: AttestationData | {
143
+ r: string;
144
+ }): Promise<boolean>;
145
+ /**
146
+ * Parse attestation data from a raw identifier string
147
+ *
148
+ * @param rawIdentifier - The JSON string from objectRawIdentifier
149
+ * @returns Parsed attestation data
150
+ * @throws Error if JSON is invalid
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * const attestationData = parseAttestationData(provenanceStatement.objectRawIdentifier);
155
+ * ```
156
+ */
157
+ export declare function parseAttestationData(rawIdentifier: string): AttestationData;
158
+ /**
159
+ * Verify that an attestation's Fide ID is correctly derived
160
+ *
161
+ * @param attestationFideId - The claimed attestation Fide ID
162
+ * @param rawIdentifier - The raw identifier JSON string
163
+ * @returns True if the Fide ID is correctly derived
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * const isValidId = await verifyAttestationFideId(
168
+ * provenanceStatement.objectFideId,
169
+ * provenanceStatement.objectRawIdentifier
170
+ * );
171
+ * ```
172
+ */
173
+ export declare function verifyAttestationFideId(attestationFideId: string, rawIdentifier: string): Promise<boolean>;
@@ -0,0 +1,188 @@
1
+ /**
2
+ * FCP SDK Attestation Utilities
3
+ *
4
+ * High-level helpers for creating and verifying attestations.
5
+ * Combines Fide ID calculation, Merkle trees, and signing.
6
+ */
7
+ import { calculateFideId } from "../../fide-id/index.js";
8
+ import { buildMerkleTree, verifyMerkleProof } from "../merkle/index.js";
9
+ // ============================================================================
10
+ // ATTESTATION CREATION
11
+ // ============================================================================
12
+ /**
13
+ * Create an attestation for a batch of statement Fide IDs
14
+ *
15
+ * This function:
16
+ * 1. Builds a Merkle tree from the statement Fide IDs
17
+ * 2. Signs the Merkle root using the provided signing function
18
+ * 3. Creates the attestation data structure
19
+ * 4. Derives the Attestation Fide ID
20
+ *
21
+ * @param statementFideIds - Array of statement Fide IDs.
22
+ * @param options - Configuration options for operation.
23
+ * @paramDefault statementFideIds ["did:fide:0x10...", "did:fide:0x10..."]
24
+ * @paramDefault options {"method":"ed25519","caip10User":"ed25519:123...","sign":"async (root) => 'signature'"}
25
+ * @returns Full attestation result including ID, data, and proofs
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { createAttestation, signEd25519 } from '@fide.work/fcp';
30
+ *
31
+ * const result = await createAttestation(
32
+ * [statement1FideId, statement2FideId],
33
+ * {
34
+ * method: 'ed25519',
35
+ * caip10User: 'ed25519::abc123...',
36
+ * sign: (root) => signEd25519(root, privateKey)
37
+ * }
38
+ * );
39
+ *
40
+ * console.log('Attestation ID:', result.attestationFideId);
41
+ * ```
42
+ */
43
+ export async function createAttestation(statementFideIds, options) {
44
+ if (statementFideIds.length === 0) {
45
+ throw new Error('Cannot create attestation from empty statement list');
46
+ }
47
+ // 1. Build Merkle tree
48
+ const merkleResult = await buildMerkleTree(statementFideIds);
49
+ const merkleRoot = merkleResult.root;
50
+ // 2. Sign the Merkle root
51
+ const signature = await options.sign(merkleRoot);
52
+ // 3. Create attestation data (with short keys, alphabetically ordered)
53
+ const attestationData = {
54
+ m: options.method,
55
+ r: merkleRoot,
56
+ s: signature,
57
+ u: options.caip10User
58
+ };
59
+ // 4. Create normalized JSON string (alphabetically ordered for determinism)
60
+ // IMPORTANT: Keys MUST be in alphabetical order (m, r, s, u) for deterministic hashing
61
+ const rawIdentifier = JSON.stringify({
62
+ m: attestationData.m,
63
+ r: attestationData.r,
64
+ s: attestationData.s,
65
+ u: attestationData.u
66
+ });
67
+ // 5. Derive attestation-like ID with fixed 0xaa prefix.
68
+ const attestationFideId = await calculateAaPrefixedId(rawIdentifier);
69
+ return {
70
+ attestationFideId,
71
+ attestationData,
72
+ rawIdentifier,
73
+ merkleRoot,
74
+ proofs: merkleResult.proofs
75
+ };
76
+ }
77
+ /**
78
+ * Create provenance statements linking each statement to the attestation
79
+ *
80
+ * These are the "Statement → prov:wasGeneratedBy → Attestation" triples
81
+ * that connect content statements to their attestation.
82
+ *
83
+ * @param statementFideIds - Array of statement Fide IDs to include in attestation
84
+ * @param attestationResult - The attestation data structure
85
+ * @returns Array of provenance statements to publish
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * const provenance = await createProvenanceStatements(
90
+ * statementFideIds,
91
+ * attestationResult
92
+ * );
93
+ * // Each provenance statement links a content statement to the attestation
94
+ * ```
95
+ */
96
+ export async function createProvenanceStatements(statementFideIds, attestationResult) {
97
+ // Get the prov:wasGeneratedBy predicate ID
98
+ const wasGeneratedByPredicateId = await calculateFideId('CreativeWork', 'CreativeWork', 'prov:wasGeneratedBy');
99
+ return statementFideIds.map(statementFideId => ({
100
+ subjectFideId: statementFideId,
101
+ predicateFideId: wasGeneratedByPredicateId,
102
+ objectFideId: attestationResult.attestationFideId,
103
+ predicateRawIdentifier: 'prov:wasGeneratedBy',
104
+ objectRawIdentifier: attestationResult.rawIdentifier
105
+ }));
106
+ }
107
+ // ============================================================================
108
+ // ATTESTATION VERIFICATION
109
+ // ============================================================================
110
+ /**
111
+ * Verify that a statement is part of an attestation
112
+ *
113
+ * This verifies the Merkle proof but does NOT verify the signature.
114
+ * Signature verification depends on the signing method and should
115
+ * be done separately using verifyEd25519 or verifyEip712.
116
+ *
117
+ * @param statementFideId - The leaf value to verify.
118
+ * @param proof - The Merkle proof path.
119
+ * @param attestationData - The attestation data.
120
+ * @paramDefault statementFideId did:fide:0x10...
121
+ * @paramDefault proof ["hash1", "hash2"]
122
+ * @paramDefault attestationData {"r":"root-hash"}
123
+ * @returns True if the statement is in the attestation
124
+ *
125
+ * @example
126
+ * ```ts
127
+ * const isInBatch = await verifyStatementInAttestation(
128
+ * statementFideId,
129
+ * proof,
130
+ * attestationData
131
+ * );
132
+ * ```
133
+ */
134
+ export async function verifyStatementInAttestation(statementFideId, proof, attestationData) {
135
+ return await verifyMerkleProof(statementFideId, proof, attestationData.r);
136
+ }
137
+ /**
138
+ * Parse attestation data from a raw identifier string
139
+ *
140
+ * @param rawIdentifier - The JSON string from objectRawIdentifier
141
+ * @returns Parsed attestation data
142
+ * @throws Error if JSON is invalid
143
+ *
144
+ * @example
145
+ * ```ts
146
+ * const attestationData = parseAttestationData(provenanceStatement.objectRawIdentifier);
147
+ * ```
148
+ */
149
+ export function parseAttestationData(rawIdentifier) {
150
+ const parsed = JSON.parse(rawIdentifier);
151
+ if (!parsed.m || !parsed.u || !parsed.r || !parsed.s) {
152
+ throw new Error('Invalid attestation data: missing required fields (m, u, r, s)');
153
+ }
154
+ return {
155
+ m: parsed.m,
156
+ u: parsed.u,
157
+ r: parsed.r,
158
+ s: parsed.s
159
+ };
160
+ }
161
+ /**
162
+ * Verify that an attestation's Fide ID is correctly derived
163
+ *
164
+ * @param attestationFideId - The claimed attestation Fide ID
165
+ * @param rawIdentifier - The raw identifier JSON string
166
+ * @returns True if the Fide ID is correctly derived
167
+ *
168
+ * @example
169
+ * ```ts
170
+ * const isValidId = await verifyAttestationFideId(
171
+ * provenanceStatement.objectFideId,
172
+ * provenanceStatement.objectRawIdentifier
173
+ * );
174
+ * ```
175
+ */
176
+ export async function verifyAttestationFideId(attestationFideId, rawIdentifier) {
177
+ const expectedId = await calculateAaPrefixedId(rawIdentifier);
178
+ return attestationFideId.toLowerCase() === expectedId.toLowerCase();
179
+ }
180
+ async function calculateAaPrefixedId(rawIdentifier) {
181
+ const bytes = new TextEncoder().encode(rawIdentifier);
182
+ const subtle = globalThis.crypto?.subtle ?? (await import("node:crypto")).webcrypto.subtle;
183
+ const digest = await subtle.digest("SHA-256", bytes);
184
+ const hashHex = Array.from(new Uint8Array(digest))
185
+ .map((byte) => byte.toString(16).padStart(2, "0"))
186
+ .join("");
187
+ return `did:fide:0xaa${hashHex.slice(-38)}`;
188
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * FCP SDK - Attestation Module
3
+ *
4
+ * Re-exports all attestation utilities.
5
+ */
6
+ export { createAttestation, createProvenanceStatements, verifyStatementInAttestation, parseAttestationData, verifyAttestationFideId, type SigningMethod, type AttestationData, type AttestationResult, type CreateAttestationOptions, type ProvenanceStatement } from "./create.js";
7
+ export { verifyAttestation, type VerifyAttestationOptions } from "./verify.js";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * FCP SDK - Attestation Module
3
+ *
4
+ * Re-exports all attestation utilities.
5
+ */
6
+ export { createAttestation, createProvenanceStatements, verifyStatementInAttestation, parseAttestationData, verifyAttestationFideId } from "./create.js";
7
+ export { verifyAttestation } from "./verify.js";
@@ -0,0 +1,56 @@
1
+ /**
2
+ * FCP SDK Attestation Verification Utilities
3
+ *
4
+ * Full verification functions that combine Merkle proof and signature verification.
5
+ */
6
+ import { type AttestationData } from "./create.js";
7
+ import type { MerkleProof } from "../merkle/index.js";
8
+ import type { SigningMethod } from "./create.js";
9
+ /**
10
+ * Options for verifying an attestation
11
+ */
12
+ export interface VerifyAttestationOptions {
13
+ /** The signing method used (`eip712`/`eip191` require `viem` to be installed). */
14
+ method: SigningMethod;
15
+ /** Public key or address for signature verification */
16
+ publicKeyOrAddress: CryptoKey | `0x${string}`;
17
+ }
18
+ /**
19
+ * Verify a complete attestation (both Merkle proof and signature)
20
+ *
21
+ * This function performs full verification:
22
+ * 1. Verifies the Merkle proof (statement is in the batch)
23
+ * 2. Verifies the signature (signer authorized the batch)
24
+ *
25
+ * @param statementFideId - The leaf value to verify in Merkle tree
26
+ * @param proof - The Merkle proof path (array of hashes from leaf to root)
27
+ * @param attestationData - The attestation data structure
28
+ * @param options - Configuration options for operation (method, public key/address, etc.)
29
+ * @returns True if both Merkle proof and signature are valid
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * // With Ed25519
34
+ * const isValid = await verifyAttestation(
35
+ * statementFideId,
36
+ * proof,
37
+ * attestationData,
38
+ * {
39
+ * method: 'ed25519',
40
+ * publicKeyOrAddress: publicKey
41
+ * }
42
+ * );
43
+ *
44
+ * // With EIP-712
45
+ * const isValid = await verifyAttestation(
46
+ * statementFideId,
47
+ * proof,
48
+ * attestationData,
49
+ * {
50
+ * method: 'eip712',
51
+ * publicKeyOrAddress: address
52
+ * }
53
+ * );
54
+ * ```
55
+ */
56
+ export declare function verifyAttestation(statementFideId: string, proof: MerkleProof, attestationData: AttestationData | string, options: VerifyAttestationOptions): Promise<boolean>;