@attestplane/attestplane 0.0.1 → 0.0.4-alpha

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 (106) hide show
  1. package/README.md +23 -9
  2. package/dist/adapter_conformance.d.ts +46 -0
  3. package/dist/adapter_conformance.d.ts.map +1 -0
  4. package/dist/adapter_conformance.js +160 -0
  5. package/dist/adapter_conformance.js.map +1 -0
  6. package/dist/adapters/langfuse.d.ts +51 -0
  7. package/dist/adapters/langfuse.d.ts.map +1 -0
  8. package/dist/adapters/langfuse.js +157 -0
  9. package/dist/adapters/langfuse.js.map +1 -0
  10. package/dist/adapters/langsmith.d.ts +53 -0
  11. package/dist/adapters/langsmith.d.ts.map +1 -0
  12. package/dist/adapters/langsmith.js +173 -0
  13. package/dist/adapters/langsmith.js.map +1 -0
  14. package/dist/adapters.d.ts +88 -0
  15. package/dist/adapters.d.ts.map +1 -0
  16. package/dist/adapters.js +109 -0
  17. package/dist/adapters.js.map +1 -0
  18. package/dist/anchoring.d.ts +119 -0
  19. package/dist/anchoring.d.ts.map +1 -0
  20. package/dist/anchoring.js +340 -0
  21. package/dist/anchoring.js.map +1 -0
  22. package/dist/canonical.d.ts +11 -2
  23. package/dist/canonical.d.ts.map +1 -1
  24. package/dist/canonical.js +44 -31
  25. package/dist/canonical.js.map +1 -1
  26. package/dist/canonical_text.d.ts +30 -0
  27. package/dist/canonical_text.d.ts.map +1 -0
  28. package/dist/canonical_text.js +100 -0
  29. package/dist/canonical_text.js.map +1 -0
  30. package/dist/der.d.ts +55 -0
  31. package/dist/der.d.ts.map +1 -0
  32. package/dist/der.js +200 -0
  33. package/dist/der.js.map +1 -0
  34. package/dist/event_payloads.d.ts +118 -0
  35. package/dist/event_payloads.d.ts.map +1 -0
  36. package/dist/event_payloads.js +348 -0
  37. package/dist/event_payloads.js.map +1 -0
  38. package/dist/event_types.d.ts +47 -0
  39. package/dist/event_types.d.ts.map +1 -0
  40. package/dist/event_types.js +63 -0
  41. package/dist/event_types.js.map +1 -0
  42. package/dist/hashchain.d.ts +1 -0
  43. package/dist/hashchain.d.ts.map +1 -1
  44. package/dist/hashchain.js +25 -1
  45. package/dist/hashchain.js.map +1 -1
  46. package/dist/index.d.ts +23 -2
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +24 -2
  49. package/dist/index.js.map +1 -1
  50. package/dist/index_version.d.ts +9 -0
  51. package/dist/index_version.d.ts.map +1 -0
  52. package/dist/index_version.js +11 -0
  53. package/dist/index_version.js.map +1 -0
  54. package/dist/intoto.d.ts +48 -0
  55. package/dist/intoto.d.ts.map +1 -0
  56. package/dist/intoto.js +106 -0
  57. package/dist/intoto.js.map +1 -0
  58. package/dist/obligations.d.ts +41 -0
  59. package/dist/obligations.d.ts.map +1 -0
  60. package/dist/obligations.js +312 -0
  61. package/dist/obligations.js.map +1 -0
  62. package/dist/proof_bundle.d.ts +186 -0
  63. package/dist/proof_bundle.d.ts.map +1 -0
  64. package/dist/proof_bundle.js +299 -0
  65. package/dist/proof_bundle.js.map +1 -0
  66. package/dist/reason_codes.d.ts +38 -0
  67. package/dist/reason_codes.d.ts.map +1 -0
  68. package/dist/reason_codes.js +97 -0
  69. package/dist/reason_codes.js.map +1 -0
  70. package/dist/replay_verifier.d.ts +43 -0
  71. package/dist/replay_verifier.d.ts.map +1 -0
  72. package/dist/replay_verifier.js +98 -0
  73. package/dist/replay_verifier.js.map +1 -0
  74. package/dist/rfc3161.d.ts +52 -0
  75. package/dist/rfc3161.d.ts.map +1 -0
  76. package/dist/rfc3161.js +640 -0
  77. package/dist/rfc3161.js.map +1 -0
  78. package/dist/settlement_verifier.d.ts +34 -0
  79. package/dist/settlement_verifier.d.ts.map +1 -0
  80. package/dist/settlement_verifier.js +139 -0
  81. package/dist/settlement_verifier.js.map +1 -0
  82. package/dist/signing/base.d.ts +101 -0
  83. package/dist/signing/base.d.ts.map +1 -0
  84. package/dist/signing/base.js +144 -0
  85. package/dist/signing/base.js.map +1 -0
  86. package/dist/signing/providers.d.ts +113 -0
  87. package/dist/signing/providers.d.ts.map +1 -0
  88. package/dist/signing/providers.js +230 -0
  89. package/dist/signing/providers.js.map +1 -0
  90. package/dist/signing/signer.d.ts +66 -0
  91. package/dist/signing/signer.d.ts.map +1 -0
  92. package/dist/signing/signer.js +146 -0
  93. package/dist/signing/signer.js.map +1 -0
  94. package/dist/signing/trust_roots.d.ts +71 -0
  95. package/dist/signing/trust_roots.d.ts.map +1 -0
  96. package/dist/signing/trust_roots.js +267 -0
  97. package/dist/signing/trust_roots.js.map +1 -0
  98. package/dist/signing/verifier_ext.d.ts +77 -0
  99. package/dist/signing/verifier_ext.d.ts.map +1 -0
  100. package/dist/signing/verifier_ext.js +340 -0
  101. package/dist/signing/verifier_ext.js.map +1 -0
  102. package/dist/verifier.d.ts +39 -0
  103. package/dist/verifier.d.ts.map +1 -0
  104. package/dist/verifier.js +374 -0
  105. package/dist/verifier.js.map +1 -0
  106. package/package.json +2 -2
package/README.md CHANGED
@@ -1,10 +1,14 @@
1
1
  # @attestplane/attestplane — TypeScript SDK
2
2
 
3
- Verifiable audit substrate for AI agents. EU AI Act Article 12 ready.
3
+ Apache-2.0 attestation and audit substrate for AI agent evidence chains.
4
4
 
5
- > **Status: alpha (v0.0.1).** Wire format is byte-locked against the Python
5
+ > **Status: alpha (v0.0.4-alpha).** Wire format is byte-locked against the Python
6
6
  > SDK's [`vectors.json`](../python/tests/conformance/vectors.json) — see
7
7
  > [ADR-0002][adr2]. APIs may still change before v0.1.0.
8
+ > The current Python CLI `attestplane verify` path is chain/report-oriented
9
+ > with ProofBundle metadata and `policy_trace_refs` closure checks. It does
10
+ > not perform full ProofBundle, signature, anchor, or compliance
11
+ > certification verification.
8
12
 
9
13
  See the [project README][project-readme] for background, governance, and
10
14
  trademark policy.
@@ -15,9 +19,16 @@ trademark policy.
15
19
  ## Install
16
20
 
17
21
  ```bash
18
- npm install @attestplane/attestplane
22
+ # Pin the alpha explicitly; v0.0.4-alpha is the next prepared alpha version.
23
+ npm install @attestplane/attestplane@alpha
24
+ # or, equivalent:
25
+ npm install @attestplane/attestplane@0.0.4-alpha
19
26
  ```
20
27
 
28
+ `npm install @attestplane/attestplane` without a tag also resolves to
29
+ the current published dist-tag. Treat the `alpha` tag as the authoritative
30
+ pre-release channel until v0.1.0 ships.
31
+
21
32
  Requires Node.js ≥ 22.
22
33
 
23
34
  ## Quickstart
@@ -55,9 +66,11 @@ will reproduce the exact byte value from the same input.
55
66
  ## What this SDK gives you
56
67
 
57
68
  - An **append-only** audit log with cryptographic integrity (SHA-256 hash chain).
58
- - Built-in **EU AI Act Art. 12(2)(a)** field coverage from day one.
69
+ - Built-in fields designed toward **EU AI Act Art. 12(2)(a)** auditability from day one.
59
70
  - Byte-identical canonical format compatible with the Python SDK.
60
71
  - Strong **GDPR pseudonymization typing** via `SubjectRef`.
72
+ - Alpha-grade verifier predicates; do not treat this SDK as production-ready
73
+ governance, compliance certification, or runtime execution authority.
61
74
 
62
75
  ## API conventions
63
76
 
@@ -76,17 +89,18 @@ Payloads must satisfy the restricted profile of ADR-0002:
76
89
  |---|---|
77
90
  | `string` (NFC-normalized UTF-8) | non-NFC strings |
78
91
  | `number` (integer, safe range) | floats, `NaN`, `Infinity` |
79
- | `bigint` (within signed 64-bit range) | bigint outside int64 |
92
+ | `number` values must be safe integers | unsafe integers; direct `bigint` |
80
93
  | `true` / `false` / `null` | — |
81
94
  | plain objects (string keys) | non-string keys; duplicate keys |
82
- | arrays | |
95
+ | arrays | sparse arrays; `undefined` items |
83
96
  | `Uint8Array` (emits as base64url no padding) | other byte types |
84
- | `Date` (UTC, encoded as RFC 3339 µs `Z`) | invalid Date |
97
+ | explicit RFC 3339 timestamp strings | direct `Date` objects in canonical JSON payloads |
85
98
 
86
99
  Violations throw `CanonicalizationError` at append time.
87
100
 
88
- For sub-millisecond precision, encode the timestamp as a string (JS `Date`
89
- only stores millisecond resolution).
101
+ `AttestSubstrate.append()` accepts `Date` at the typed SDK boundary for
102
+ `AuditEvent.timestamp` and converts it explicitly before hashing. Payloads
103
+ should carry timestamps as strings when they need to be part of canonical JSON.
90
104
 
91
105
  ## Development
92
106
 
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Adapter-conformance fixture replayer (ADR-0014 P2.2).
3
+ *
4
+ * TypeScript mirror of `attestplane.adapter_conformance` (Python).
5
+ * Loads a fixture file, calls `adapter.translate()` per case, asserts
6
+ * canonical-bytes equality against `expected_event_draft`. Pure — no
7
+ * I/O beyond the fixture file read.
8
+ */
9
+ import type { EventDraft } from './types.js';
10
+ export interface AdapterCaseResult {
11
+ readonly case_name: string;
12
+ readonly ok: boolean;
13
+ readonly reason: string | null;
14
+ readonly expected_canonical_hash: string | null;
15
+ readonly actual_canonical_hash: string | null;
16
+ }
17
+ export interface AdapterConformanceReport {
18
+ readonly fixture_path: string;
19
+ readonly runtime_kind: string;
20
+ readonly fixture_version: number;
21
+ readonly cases_total: number;
22
+ readonly cases_passed: number;
23
+ readonly cases_failed: number;
24
+ readonly results: readonly AdapterCaseResult[];
25
+ readonly ok: boolean;
26
+ }
27
+ export declare class AdapterConformanceError extends Error {
28
+ constructor(message: string);
29
+ }
30
+ export interface ReplayOptions {
31
+ /** Optional callback to convert raw `runtime_event_input` into the
32
+ * runtime-event type the adapter's `translate()` expects. */
33
+ readonly pre_translate?: (raw: Record<string, unknown>) => unknown;
34
+ }
35
+ /** An adapter-shaped object: has a `translate()` method returning an `EventDraft`. */
36
+ export interface TranslateAdapter<RE = unknown> {
37
+ translate(runtimeEvent: RE): EventDraft;
38
+ }
39
+ /**
40
+ * Replay every case in `fixturePath` against `adapter.translate()`.
41
+ *
42
+ * `report.ok` is true iff every case's adapter output matches its
43
+ * `expected_event_draft` byte-equal under canonical-JSON.
44
+ */
45
+ export declare function replayFixture(fixturePath: string, adapter: TranslateAdapter, options?: ReplayOptions): AdapterConformanceReport;
46
+ //# sourceMappingURL=adapter_conformance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter_conformance.d.ts","sourceRoot":"","sources":["../src/adapter_conformance.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,YAAY,CAAC;AAEzD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/C;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC/C,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,uBAAwB,SAAQ,KAAK;gBACpC,OAAO,EAAE,MAAM;CAI5B;AA+HD,MAAM,WAAW,aAAa;IAC5B;kEAC8D;IAC9D,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;CACpE;AAED,sFAAsF;AACtF,MAAM,WAAW,gBAAgB,CAAC,EAAE,GAAG,OAAO;IAC5C,SAAS,CAAC,YAAY,EAAE,EAAE,GAAG,UAAU,CAAC;CACzC;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE,aAAkB,GAC1B,wBAAwB,CAyD1B"}
@@ -0,0 +1,160 @@
1
+ // SPDX-FileCopyrightText: 2026 The Attestplane Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Adapter-conformance fixture replayer (ADR-0014 P2.2).
5
+ *
6
+ * TypeScript mirror of `attestplane.adapter_conformance` (Python).
7
+ * Loads a fixture file, calls `adapter.translate()` per case, asserts
8
+ * canonical-bytes equality against `expected_event_draft`. Pure — no
9
+ * I/O beyond the fixture file read.
10
+ */
11
+ import { createHash } from 'node:crypto';
12
+ import { readFileSync } from 'node:fs';
13
+ import { canonicalize } from './canonical.js';
14
+ export class AdapterConformanceError extends Error {
15
+ constructor(message) {
16
+ super(message);
17
+ this.name = 'AdapterConformanceError';
18
+ }
19
+ }
20
+ function subjectRefToDict(ref) {
21
+ if (ref === null || ref === undefined)
22
+ return null;
23
+ return { scheme: ref.scheme, value: ref.value };
24
+ }
25
+ function eventDraftToDict(draft) {
26
+ return {
27
+ event_type: draft.event_type,
28
+ actor: draft.actor,
29
+ payload: draft.payload,
30
+ subject_ref: subjectRefToDict(draft.subject_ref),
31
+ session_id: draft.session_id,
32
+ reference_db_ref: draft.reference_db_ref,
33
+ matched_input_ref: draft.matched_input_ref,
34
+ human_verifier: subjectRefToDict(draft.human_verifier),
35
+ };
36
+ }
37
+ function canonicalBytesHash(d) {
38
+ return createHash('sha256').update(canonicalize(d)).digest('hex');
39
+ }
40
+ function loadAndValidateFixture(fixturePath) {
41
+ let raw;
42
+ try {
43
+ raw = JSON.parse(readFileSync(fixturePath, 'utf-8'));
44
+ }
45
+ catch (exc) {
46
+ throw new AdapterConformanceError(`cannot load fixture ${fixturePath}: ${exc.message}`);
47
+ }
48
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
49
+ throw new AdapterConformanceError(`fixture ${fixturePath}: top level must be object, got ${Array.isArray(raw) ? 'array' : raw === null ? 'null' : typeof raw}`);
50
+ }
51
+ const obj = raw;
52
+ if (obj.$schema_version !== 1) {
53
+ throw new AdapterConformanceError(`fixture ${fixturePath}: $schema_version must be 1, got ${JSON.stringify(obj.$schema_version)}`);
54
+ }
55
+ if (obj.fixture_kind !== 'adapter_conformance') {
56
+ throw new AdapterConformanceError(`fixture ${fixturePath}: fixture_kind must be 'adapter_conformance', got ${JSON.stringify(obj.fixture_kind)}`);
57
+ }
58
+ if (typeof obj.runtime_kind !== 'string' || obj.runtime_kind.length === 0) {
59
+ throw new AdapterConformanceError(`fixture ${fixturePath}: runtime_kind must be non-empty string`);
60
+ }
61
+ if (typeof obj.fixture_version !== 'number' ||
62
+ !Number.isInteger(obj.fixture_version) ||
63
+ obj.fixture_version < 1) {
64
+ throw new AdapterConformanceError(`fixture ${fixturePath}: fixture_version must be integer >= 1`);
65
+ }
66
+ if (!Array.isArray(obj.cases) || obj.cases.length === 0) {
67
+ throw new AdapterConformanceError(`fixture ${fixturePath}: cases must be non-empty array`);
68
+ }
69
+ const seenNames = new Set();
70
+ for (let i = 0; i < obj.cases.length; i++) {
71
+ const c = obj.cases[i];
72
+ if (c === null || typeof c !== 'object' || Array.isArray(c)) {
73
+ throw new AdapterConformanceError(`fixture ${fixturePath}: cases[${i}] must be object`);
74
+ }
75
+ const co = c;
76
+ if (typeof co.name !== 'string' || co.name.length === 0) {
77
+ throw new AdapterConformanceError(`fixture ${fixturePath}: cases[${i}].name must be non-empty string`);
78
+ }
79
+ if (seenNames.has(co.name)) {
80
+ throw new AdapterConformanceError(`fixture ${fixturePath}: duplicate case name ${JSON.stringify(co.name)}`);
81
+ }
82
+ seenNames.add(co.name);
83
+ if (!('runtime_event_input' in co)) {
84
+ throw new AdapterConformanceError(`fixture ${fixturePath}: cases[${i}] missing runtime_event_input`);
85
+ }
86
+ if (!('expected_event_draft' in co)) {
87
+ throw new AdapterConformanceError(`fixture ${fixturePath}: cases[${i}] missing expected_event_draft`);
88
+ }
89
+ if (co.expected_event_draft === null ||
90
+ typeof co.expected_event_draft !== 'object' ||
91
+ Array.isArray(co.expected_event_draft)) {
92
+ throw new AdapterConformanceError(`fixture ${fixturePath}: cases[${i}].expected_event_draft must be object`);
93
+ }
94
+ }
95
+ return obj;
96
+ }
97
+ /**
98
+ * Replay every case in `fixturePath` against `adapter.translate()`.
99
+ *
100
+ * `report.ok` is true iff every case's adapter output matches its
101
+ * `expected_event_draft` byte-equal under canonical-JSON.
102
+ */
103
+ export function replayFixture(fixturePath, adapter, options = {}) {
104
+ const fixture = loadAndValidateFixture(fixturePath);
105
+ const results = [];
106
+ let passed = 0;
107
+ let failed = 0;
108
+ for (const c of fixture.cases) {
109
+ const expectedHash = canonicalBytesHash(c.expected_event_draft);
110
+ try {
111
+ const runtimeEvent = options.pre_translate !== undefined
112
+ ? options.pre_translate(c.runtime_event_input)
113
+ : c.runtime_event_input;
114
+ const actualDraft = adapter.translate(runtimeEvent);
115
+ const actual = eventDraftToDict(actualDraft);
116
+ const actualHash = canonicalBytesHash(actual);
117
+ if (actualHash === expectedHash) {
118
+ results.push({
119
+ case_name: c.name,
120
+ ok: true,
121
+ reason: null,
122
+ expected_canonical_hash: expectedHash,
123
+ actual_canonical_hash: actualHash,
124
+ });
125
+ passed++;
126
+ }
127
+ else {
128
+ results.push({
129
+ case_name: c.name,
130
+ ok: false,
131
+ reason: `canonical-bytes mismatch (expected hash ${expectedHash}, got ${actualHash})`,
132
+ expected_canonical_hash: expectedHash,
133
+ actual_canonical_hash: actualHash,
134
+ });
135
+ failed++;
136
+ }
137
+ }
138
+ catch (exc) {
139
+ results.push({
140
+ case_name: c.name,
141
+ ok: false,
142
+ reason: `adapter raised: ${exc.name}: ${exc.message}`,
143
+ expected_canonical_hash: expectedHash,
144
+ actual_canonical_hash: null,
145
+ });
146
+ failed++;
147
+ }
148
+ }
149
+ return {
150
+ fixture_path: fixturePath,
151
+ runtime_kind: fixture.runtime_kind,
152
+ fixture_version: fixture.fixture_version,
153
+ cases_total: fixture.cases.length,
154
+ cases_passed: passed,
155
+ cases_failed: failed,
156
+ results,
157
+ ok: failed === 0,
158
+ };
159
+ }
160
+ //# sourceMappingURL=adapter_conformance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter_conformance.js","sourceRoot":"","sources":["../src/adapter_conformance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * LangFuse → Attestplane evidence-event adapter (TypeScript port of
3
+ * `sdk/python/src/attestplane/adapters/langfuse.py`).
4
+ *
5
+ * Byte-identical translation semantics with the Python adapter.
6
+ *
7
+ * Pure function per GenericRuntimeAdapter contract: no I/O, no
8
+ * LangFuse API calls.
9
+ *
10
+ * Trust boundary (ADR-0004 § 4): adapter consumes the public
11
+ * LangFuse Observation shape; LangFuse / ClickHouse do not endorse
12
+ * this adapter (see docs/policy/forbidden_claims.md § G).
13
+ *
14
+ * Redaction (ADR-0008 § Boundary anti-requirements):
15
+ * - Raw input / output never copied to payload — only SHA-256 hashes.
16
+ * - status_message truncated to 200 chars before placing in error_code.
17
+ * - user_id (from parent Trace) wrapped in SubjectRef(scheme="opaque").
18
+ *
19
+ * Observation type → event_type mapping:
20
+ * GENERATION / SPAN / EVENT → tool_call_event with payload.kind set.
21
+ *
22
+ * Level → result_status mapping:
23
+ * ERROR → "ERROR"; everything else → "OK" (WARNING preserved as
24
+ * payload.level but not flipping status).
25
+ */
26
+ import { GenericRuntimeAdapter } from '../adapters.js';
27
+ import { type EventDraft } from '../types.js';
28
+ export interface LangFuseObservation {
29
+ readonly id: string;
30
+ readonly trace_id: string;
31
+ readonly type: string;
32
+ readonly name?: string | null;
33
+ readonly start_time?: Date | null;
34
+ readonly end_time?: Date | null;
35
+ readonly input?: unknown;
36
+ readonly output?: unknown;
37
+ readonly level?: string | null;
38
+ readonly metadata?: Record<string, unknown>;
39
+ readonly status_message?: string | null;
40
+ readonly model?: string | null;
41
+ readonly user_id?: string | null;
42
+ }
43
+ export declare class LangFuseAdapter extends GenericRuntimeAdapter<LangFuseObservation> {
44
+ readonly runtime_name = "langfuse";
45
+ readonly schema_version = 1;
46
+ translate(runtime_event: LangFuseObservation): EventDraft;
47
+ static fromDict(raw: Record<string, unknown>, options?: {
48
+ readonly user_id?: string;
49
+ }): LangFuseObservation;
50
+ }
51
+ //# sourceMappingURL=langfuse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"langfuse.d.ts","sourceRoot":"","sources":["../../src/adapters/langfuse.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,OAAO,EAA2B,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEhF,OAAO,EAAE,KAAK,UAAU,EAAkC,MAAM,aAAa,CAAC;AAK9E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAiCD,qBAAa,eAAgB,SAAQ,qBAAqB,CAAC,mBAAmB,CAAC;IAC7E,QAAQ,CAAC,YAAY,cAAc;IACnC,QAAQ,CAAC,cAAc,KAAK;IAE5B,SAAS,CAAC,aAAa,EAAE,mBAAmB,GAAG,UAAU;IA+DzD,MAAM,CAAC,QAAQ,CACb,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GACtC,mBAAmB;CA4CvB"}
@@ -0,0 +1,157 @@
1
+ // SPDX-FileCopyrightText: 2026 The Attestplane Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * LangFuse → Attestplane evidence-event adapter (TypeScript port of
5
+ * `sdk/python/src/attestplane/adapters/langfuse.py`).
6
+ *
7
+ * Byte-identical translation semantics with the Python adapter.
8
+ *
9
+ * Pure function per GenericRuntimeAdapter contract: no I/O, no
10
+ * LangFuse API calls.
11
+ *
12
+ * Trust boundary (ADR-0004 § 4): adapter consumes the public
13
+ * LangFuse Observation shape; LangFuse / ClickHouse do not endorse
14
+ * this adapter (see docs/policy/forbidden_claims.md § G).
15
+ *
16
+ * Redaction (ADR-0008 § Boundary anti-requirements):
17
+ * - Raw input / output never copied to payload — only SHA-256 hashes.
18
+ * - status_message truncated to 200 chars before placing in error_code.
19
+ * - user_id (from parent Trace) wrapped in SubjectRef(scheme="opaque").
20
+ *
21
+ * Observation type → event_type mapping:
22
+ * GENERATION / SPAN / EVENT → tool_call_event with payload.kind set.
23
+ *
24
+ * Level → result_status mapping:
25
+ * ERROR → "ERROR"; everything else → "OK" (WARNING preserved as
26
+ * payload.level but not flipping status).
27
+ */
28
+ import { createHash } from 'node:crypto';
29
+ import { AdapterTranslationError, GenericRuntimeAdapter } from '../adapters.js';
30
+ import { TOOL_CALL_EVENT } from '../event_types.js';
31
+ import { makeEventDraft, makeSubjectRef } from '../types.js';
32
+ const KNOWN_OBSERVATION_TYPES = new Set(['GENERATION', 'SPAN', 'EVENT']);
33
+ const KNOWN_LEVELS = new Set(['DEFAULT', 'DEBUG', 'WARNING', 'ERROR']);
34
+ function _canonicalReplacer() {
35
+ return function (_key, value) {
36
+ if (value === undefined)
37
+ return undefined;
38
+ if (value instanceof Date)
39
+ return value.toISOString();
40
+ if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
41
+ const sorted = {};
42
+ const obj = value;
43
+ for (const k of Object.keys(obj).sort()) {
44
+ sorted[k] = obj[k];
45
+ }
46
+ return sorted;
47
+ }
48
+ return value;
49
+ };
50
+ }
51
+ function _hashJson(value) {
52
+ const sorted = JSON.parse(JSON.stringify(value, _canonicalReplacer()));
53
+ const compact = JSON.stringify(sorted);
54
+ return createHash('sha256').update(compact, 'utf-8').digest('hex');
55
+ }
56
+ function _truncate(text, n = 200) {
57
+ if (text.length <= n)
58
+ return text;
59
+ return `${text.slice(0, n - 3)}...`;
60
+ }
61
+ function _levelToStatus(level) {
62
+ return level === 'ERROR' ? 'ERROR' : 'OK';
63
+ }
64
+ export class LangFuseAdapter extends GenericRuntimeAdapter {
65
+ runtime_name = 'langfuse';
66
+ schema_version = 1;
67
+ translate(runtime_event) {
68
+ if (typeof runtime_event !== 'object' ||
69
+ runtime_event === null ||
70
+ typeof runtime_event.id !== 'string' ||
71
+ typeof runtime_event.trace_id !== 'string' ||
72
+ typeof runtime_event.type !== 'string') {
73
+ throw new AdapterTranslationError(`expected LangFuseObservation object, got ${runtime_event === null ? 'null' : typeof runtime_event}`);
74
+ }
75
+ const obs = runtime_event;
76
+ const kind = KNOWN_OBSERVATION_TYPES.has(obs.type) ? obs.type.toLowerCase() : 'unknown';
77
+ const resultStatus = _levelToStatus(obs.level);
78
+ const payload = {
79
+ kind,
80
+ tool_name: `langfuse.${kind}.${obs.name ?? 'unnamed'}`,
81
+ tool_call_id: obs.id,
82
+ result_status: resultStatus,
83
+ };
84
+ if (obs.input !== undefined && obs.input !== null) {
85
+ payload.arguments_hash = _hashJson(obs.input);
86
+ }
87
+ else {
88
+ // Schema requires arguments_hash always present; hash empty dict.
89
+ payload.arguments_hash = _hashJson({});
90
+ }
91
+ if (obs.output !== undefined && obs.output !== null) {
92
+ payload.result_hash = _hashJson(obs.output);
93
+ }
94
+ if (obs.start_time != null && obs.end_time != null) {
95
+ const ms = obs.end_time.getTime() - obs.start_time.getTime();
96
+ payload.latency_ms = Math.trunc(ms);
97
+ }
98
+ if (obs.status_message && resultStatus === 'ERROR') {
99
+ payload.error_code = _truncate(obs.status_message);
100
+ }
101
+ if (obs.model) {
102
+ payload.tool_version = obs.model;
103
+ }
104
+ if (obs.level && KNOWN_LEVELS.has(obs.level) && obs.level !== 'DEFAULT') {
105
+ payload.level = obs.level;
106
+ }
107
+ return makeEventDraft({
108
+ event_type: TOOL_CALL_EVENT,
109
+ actor: `langfuse://${kind}/${obs.name ?? 'unnamed'}`,
110
+ payload,
111
+ subject_ref: obs.user_id ? makeSubjectRef('opaque', obs.user_id) : null,
112
+ session_id: obs.trace_id,
113
+ });
114
+ }
115
+ static fromDict(raw, options) {
116
+ const required = ['id', 'trace_id', 'type'];
117
+ const missing = required.filter((k) => !(k in raw));
118
+ if (missing.length > 0) {
119
+ throw new AdapterTranslationError(`LangFuse observation dict missing required fields: ${JSON.stringify(missing.sort())}`);
120
+ }
121
+ const parseDt = (value) => {
122
+ if (value == null)
123
+ return null;
124
+ if (value instanceof Date)
125
+ return value;
126
+ if (typeof value === 'string') {
127
+ const normalized = value.endsWith('Z') ? value.replace('Z', '+00:00') : value;
128
+ const d = new Date(normalized);
129
+ if (Number.isNaN(d.getTime())) {
130
+ throw new AdapterTranslationError(`unparsable datetime ${JSON.stringify(value)}`);
131
+ }
132
+ return d;
133
+ }
134
+ throw new AdapterTranslationError(`datetime field has type ${typeof value}`);
135
+ };
136
+ const metadata = raw.metadata ?? {};
137
+ if (typeof metadata !== 'object' || Array.isArray(metadata)) {
138
+ throw new AdapterTranslationError('metadata must be an object');
139
+ }
140
+ return {
141
+ id: String(raw.id),
142
+ trace_id: String(raw.trace_id),
143
+ type: String(raw.type),
144
+ name: raw.name ?? null,
145
+ start_time: parseDt(raw.start_time),
146
+ end_time: parseDt(raw.end_time),
147
+ input: raw.input,
148
+ output: raw.output,
149
+ level: raw.level ?? null,
150
+ metadata,
151
+ status_message: raw.status_message ?? null,
152
+ model: raw.model ?? null,
153
+ user_id: options?.user_id ?? null,
154
+ };
155
+ }
156
+ }
157
+ //# sourceMappingURL=langfuse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"langfuse.js","sourceRoot":"","sources":["../../src/adapters/langfuse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * LangSmith → Attestplane evidence-event adapter (TypeScript port of
3
+ * `sdk/python/src/attestplane/adapters/langsmith.py`).
4
+ *
5
+ * Byte-identical translation semantics with the Python adapter:
6
+ * given the same LangSmith Run, both adapters produce the same
7
+ * EventDraft fields (event_type, actor, payload, subject_ref,
8
+ * session_id, reference_db_ref).
9
+ *
10
+ * Pure function per GenericRuntimeAdapter contract: no I/O, no
11
+ * LangSmith API calls.
12
+ *
13
+ * Trust boundary (ADR-0004 § 4): adapter consumes the public
14
+ * LangSmith Run shape, not LangChain proprietary code. LangChain
15
+ * does not endorse this adapter; see docs/policy/forbidden_claims.md
16
+ * § G.
17
+ *
18
+ * Redaction (ADR-0008 § Boundary anti-requirements):
19
+ * - Raw inputs / outputs are NEVER copied to payload — only SHA-256
20
+ * hashes go in `arguments_hash` / `result_hash`.
21
+ * - Error strings are truncated to 200 chars to limit PII leakage.
22
+ * - end_user_id (from LangSmith metadata.user_id) is wrapped in
23
+ * SubjectRef(scheme="opaque").
24
+ *
25
+ * Run type → event_type mapping is identical to the Python adapter:
26
+ * all run_types map to `tool_call_event` in v1; payload.kind carries
27
+ * the LangSmith run_type for downstream filtering.
28
+ */
29
+ import { GenericRuntimeAdapter } from '../adapters.js';
30
+ import { type EventDraft } from '../types.js';
31
+ export interface LangSmithRun {
32
+ readonly id: string;
33
+ readonly name: string;
34
+ readonly run_type: string;
35
+ readonly start_time: Date;
36
+ readonly end_time?: Date | null;
37
+ readonly inputs?: Record<string, unknown>;
38
+ readonly outputs?: Record<string, unknown> | null;
39
+ readonly error?: string | null;
40
+ readonly trace_id?: string | null;
41
+ readonly parent_run_id?: string | null;
42
+ readonly status?: string | null;
43
+ readonly tags?: readonly string[];
44
+ readonly metadata?: Record<string, unknown>;
45
+ readonly end_user_id?: string | null;
46
+ }
47
+ export declare class LangSmithAdapter extends GenericRuntimeAdapter<LangSmithRun> {
48
+ readonly runtime_name = "langsmith";
49
+ readonly schema_version = 1;
50
+ translate(runtime_event: LangSmithRun): EventDraft;
51
+ static fromDict(raw: Record<string, unknown>): LangSmithRun;
52
+ }
53
+ //# sourceMappingURL=langsmith.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"langsmith.d.ts","sourceRoot":"","sources":["../../src/adapters/langsmith.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,EAA2B,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEhF,OAAO,EAAE,KAAK,UAAU,EAAkC,MAAM,aAAa,CAAC;AAY9E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,IAAI,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAClD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtC;AAmCD,qBAAa,gBAAiB,SAAQ,qBAAqB,CAAC,YAAY,CAAC;IACvE,QAAQ,CAAC,YAAY,eAAe;IACpC,QAAQ,CAAC,cAAc,KAAK;IAE5B,SAAS,CAAC,aAAa,EAAE,YAAY,GAAG,UAAU;IAyDlD,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY;CAoD5D"}