@atrib/sdk 0.1.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 ADDED
@@ -0,0 +1,525 @@
1
+ # @atrib/sdk
2
+
3
+ Consolidated atrib client SDK: two verbs over the substrate — **`attest()`**
4
+ (write) and **`recall()`** (read) — plus the complete [§1](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#1-attribution-record-format) record layer
5
+ re-exported from `@atrib/mcp` so application code needs exactly one import.
6
+
7
+ This package is a consolidation, not a greenfield: it adds **no new
8
+ canonicalization, hashing, or signing implementation**. Every write
9
+ terminates in `@atrib/emit`'s `handleEmit` pipeline (records are
10
+ byte-identical to wrapper-signed and primitive-signed records), and every
11
+ cryptographic primitive is the existing `@atrib/mcp` one.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pnpm add @atrib/sdk
17
+ ```
18
+
19
+ Version 0.1.0 is first-published manually. Later releases use npm Trusted
20
+ Publisher through `release.yml`. `@atrib/recall`, `@atrib/verify`, and
21
+ `@atrib/verify-mcp` are optional peers — install them alongside for the
22
+ in-process recall and verify fallbacks; without them those paths degrade to
23
+ a typed unavailable outcome per the degradation contract below.
24
+
25
+ Verify a local build with `pnpm --filter @atrib/sdk test`.
26
+
27
+ ## Topology: daemon-first
28
+
29
+ Per [D120](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d120-local-substrate-coordinator-keeps-startup-spawn-sidecars-wrapper-owned) and the redesign upgrade path, the local primitives runtime is the
30
+ default peer. The SDK talks MCP Streamable HTTP to it
31
+ (`$ATRIB_PRIMITIVES_HTTP_ENDPOINT`, default `http://127.0.0.1:8796/mcp`)
32
+ and falls back to in-process engines when no daemon is reachable:
33
+
34
+ | Verb | Daemon path | In-process fallback |
35
+ | --- | --- | --- |
36
+ | `attest()` | `emit` tool (daemon-owned key) | `emitInProcess()` from `@atrib/emit` (caller-owned key) |
37
+ | `recall({shape: 'history'})` | `recall_my_attribution_history` | `recall()` from `@atrib/recall` (optional peer) |
38
+ | `recall({shape: 'verify'})` | `atrib-verify` | `handleAtribVerify()` from `@atrib/verify-mcp` (optional peer) |
39
+ | other recall shapes | matching runtime tool | degraded warning outcome (v0) |
40
+
41
+ `@atrib/recall` and `@atrib/verify-mcp` are **optional peer dependencies**
42
+ loaded lazily (the P047 pattern): without them installed, those two
43
+ in-process fallbacks degrade to a typed unavailable outcome with a
44
+ warning instead of an import failure. `@atrib/emit` stays a hard
45
+ dependency so the write path always works.
46
+
47
+ The SDK is **semantically stateless** (stateless-MCP-native posture):
48
+ `context_id` and chain tokens are explicit per-request values; nothing
49
+ rides on the MCP protocol session, which remains a transport detail of the
50
+ current runtime until the 2026-07-28 stateless transport ships.
51
+
52
+ ## Usage
53
+
54
+ ```ts
55
+ import { createAtribClient } from '@atrib/sdk'
56
+
57
+ const client = createAtribClient()
58
+
59
+ // Write: observation (default), or annotate/revise via ref.kind
60
+ const result = await client.attest({
61
+ content: { what: 'chose sqlite over postgres', why_noted: 'deployment constraint' },
62
+ })
63
+
64
+ await client.attest({
65
+ content: { summary: 'supersedes the sqlite decision', reason: 'scale changed' },
66
+ ref: { kind: 'revises', record_hash: result.record_hash! },
67
+ })
68
+
69
+ // Read: one verb, shape-discriminated
70
+ const history = await client.recall({ shape: 'history', limit: 10 })
71
+ const walk = await client.recall({ shape: 'walk', from_record_hash: result.record_hash! })
72
+
73
+ await client.close()
74
+ ```
75
+
76
+ `summarize` is deliberately **not** a recall shape: synthesis belongs to
77
+ the calling harness/model; the SDK returns verified raw material.
78
+
79
+ ## Degradation contract ([§5.8](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#58-degradation-contract))
80
+
81
+ Operational failures never throw and never block: daemon unreachable →
82
+ fallback; no signing key → pass-through result with a warning; log
83
+ submission is non-blocking with bounded retry (via the existing
84
+ `@atrib/mcp` submission queue). The only throw paths are contradictory
85
+ inputs (programmer error), e.g. `ref.kind: 'revises'` with
86
+ `event_type: 'annotation'`.
87
+
88
+ ## Anchors ([D138](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d138-anchor-plurality-as-the-default-trust-posture), [§2.11.7-§2.11.13](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#2117-anchors-generalizing-the-replication-target))
89
+
90
+ `anchors` config takes a **set** of anchor descriptors — bare strings
91
+ (atrib-log [§2.6.1](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#261-submit-entry)
92
+ endpoints) or `{ url | endpoint, anchor_type?, ... }` objects covering
93
+ the [§2.11.8](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#2118-anchor-type-registry)
94
+ registry (`atrib-log`, `sigstore-rekor`, `rfc3161-tsa`,
95
+ `opentimestamps`). In-process attests fan out to **every** configured
96
+ anchor through `@atrib/mcp`'s `createAnchorFanout` (fire-and-forget per
97
+ [§5.3.5](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#535-log-submission));
98
+ no anchor config at all resolves to `BUILT_IN_DEFAULT_ANCHOR_SET` (two
99
+ independent anchors, [§2.11.12](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#21112-producer-side-anchor-posture)
100
+ rule 1). A sub-plurality set (< 2 anchors) warns and writes the
101
+ `_local.anchor_config` sidecar degradation marker unless
102
+ `allowSingleAnchor: true` states it is deliberate. The resolved posture
103
+ surfaces as `anchor_posture` on `AttestResult`; `flushAnchors()` gives a
104
+ bounded wait on pending legs. Anchoring never touches signed bytes and
105
+ never blocks the write.
106
+
107
+ ## Extension receipts (opt-in)
108
+
109
+ With `attributionReceipts: true`, the daemon client parses
110
+ `dev.atrib/attribution` attestation receipts from tool results' `_meta`
111
+ ([D141](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d141-devatribattribution-first-class-mcp-extension-sep-2133),
112
+ extension v0.1): the propagation token, a receipt naming the record the
113
+ server already signed (`log_submission` is a queue status, never an
114
+ awaited proof), and optionally the full signed record for immediate
115
+ Tier-3 re-verification. Each parsed block is run through `@atrib/mcp`'s
116
+ `verifyAttributionReceipt` (extension spec [§6.2](https://github.com/creatornader/atrib/blob/main/docs/extensions/dev.atrib-attribution/v0.1.md#62-receipt-block) integrity check) and
117
+ surfaces as `attribution_receipt: { block, verification }` on
118
+ attest/recall results. Receipts are advisory — trust derives from
119
+ verifying signed records, never from the receipt.
120
+
121
+ ## Evidence envelopes ([D137](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d137-universal-evidence-envelope-as-the-single-protocol-level-attachment-model), [§5.5.7](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#557-universal-evidence-envelope))
122
+
123
+ The universal envelope (profile type URI, four-tier ladder `declared →
124
+ shape → attested → verified`, payload commitment, verifier facts) is the
125
+ single attachment model for external evidence; the legacy `protocol`
126
+ string set is frozen. The SDK ships the structural types/helpers plus
127
+ production and validation: `buildEvidenceEnvelope` computes the payload
128
+ commitment (JCS or raw hash rule) and `validateEvidenceEnvelope` applies
129
+ the normative shape rules — both delegate to the optional peer
130
+ `@atrib/verify` and degrade with a warning when it is not installed.
131
+ Envelopes live outside signed bytes (mirror sidecar, archive evidence
132
+ projection, verifier results, host-owned packets).
133
+
134
+ ## API reference
135
+
136
+ Everything below is exported from the package root (`import { … } from
137
+ '@atrib/sdk'`). The surface splits into the SDK layer (the two verbs, the
138
+ config, the daemon transport, the hash helpers, the evidence and receipt
139
+ types) and the record layer re-exported verbatim from `@atrib/mcp` and
140
+ `@atrib/emit`.
141
+
142
+ ### `createAtribClient(config?)` → `AtribClient`
143
+
144
+ Builds a client from an [`AtribClientConfig`](#atribclientconfig)
145
+ (default `{}`). Construction is cheap and never throws on operational
146
+ problems: the daemon connection is lazy (first call), the in-process
147
+ signing key resolves lazily on the first attest that needs it, and anchor
148
+ normalization collects warnings instead of erroring.
149
+
150
+ ```ts
151
+ interface AtribClient {
152
+ attest(input: AttestInput): Promise<AttestResult>
153
+ recall<T = unknown>(query: RecallQuery): Promise<RecallOutcome<T>>
154
+ flushAnchors(): Promise<void> // bounded wait on pending anchor legs; never throws
155
+ close(): Promise<void>
156
+ }
157
+ ```
158
+
159
+ **Throw vs degrade.** Both verbs follow the
160
+ [§5.8](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#58-degradation-contract)
161
+ degradation contract: operational failures (daemon unreachable, tool
162
+ error, missing key, missing optional peer, log unreachable) never throw —
163
+ they degrade into `warnings` on the result, with `via: 'none'` when
164
+ nothing could serve the call. The only throw paths are contradictory or
165
+ malformed **inputs** (programmer error): a `ref.kind` that contradicts an
166
+ explicit `event_type`, an unknown `ref.kind`, an unknown recall `shape`,
167
+ or an input shape that fails `emitInProcess`'s schema validation.
168
+
169
+ **`attest(input)` semantics.** Maps `AttestInput` to the shared
170
+ `EmitInput` argument shape via `buildEmitArgs` (exported; throws
171
+ `TypeError` on contradictory input — the write verb's only throw path),
172
+ then tries paths in order:
173
+
174
+ 1. **Daemon** (`daemon.mode` `'prefer'` or `'require'`): calls the `emit`
175
+ tool on the primitives runtime. The daemon owns the signing key. A
176
+ structurally-garbage daemon result (no `record_hash` string) counts as
177
+ a daemon failure, not a silent all-null success.
178
+ 2. **In-process** (`'prefer'` after a daemon failure, or `'off'`): resolves
179
+ the caller-owned key (see `key` in
180
+ [`AtribClientConfig`](#atribclientconfig)) and calls `emitInProcess`
181
+ from `@atrib/emit` with the configured `producer` and the primary
182
+ atrib-log anchor as `logEndpoint`, then reads the freshly signed
183
+ record back from the mirror tail and fans it out to every configured
184
+ anchor via `createAnchorFanout`
185
+ ([D138](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d138-anchor-plurality-as-the-default-trust-posture);
186
+ fire-and-forget per [§5.3.5](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#535-log-submission)
187
+ — the primary log receiving the record twice is idempotent-safe per
188
+ [§2.6.1](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#261-submit-entry)
189
+ step 6), stamping the resolved `anchor_posture` on the result. No key
190
+ → pass-through result (`via: 'none'`, `record_hash: null`) with a
191
+ warning, per
192
+ [§5.8](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#58-degradation-contract)
193
+ rule 5. The daemon path never consults the client's fan-out: the
194
+ daemon owns its own anchors.
195
+
196
+ Under `daemon.mode: 'require'`, a daemon failure returns the degraded
197
+ `via: 'none'` result directly — it never falls back and never throws.
198
+
199
+ **`recall(query)` semantics.** Resolves the shape (`query.shape`, default
200
+ `'history'`), maps it to the physical tool name via `SHAPE_TO_TOOL`
201
+ (exported), strips the SDK-only `shape` discriminator and `undefined`
202
+ values, and injects the client's default `context_id` for the
203
+ `session_chain` and `orphans` shapes when the query omits it. Then:
204
+ daemon first; on failure, the in-process fallback for the two shapes
205
+ whose engines are exported as libraries today (`history`, `verify`);
206
+ every other shape degrades to `via: 'none'` with a warning naming the
207
+ runtime tool to use instead. See the
208
+ [shape table](#recallquery-shapes) for the full routing.
209
+
210
+ **`close()`** closes the daemon transport if one was opened. Best-effort;
211
+ never throws. Safe to call when `daemon.mode` was `'off'`.
212
+
213
+ ### `AttestInput` / `AttestRef`
214
+
215
+ One write shape collapsing emit / annotate / revise. `ref` is the
216
+ discriminator:
217
+
218
+ ```ts
219
+ interface AttestRef {
220
+ kind: 'annotates' | 'revises'
221
+ record_hash: string // sha256:<64-hex>
222
+ }
223
+ ```
224
+
225
+ | Field | Type | Required | Meaning |
226
+ | --- | --- | --- | --- |
227
+ | `content` | `Record<string, unknown>` | yes | The content being attested. Committed via default `args_hash` = `sha256(JCS(content))` per [D099](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d099-explicit-emit-records-commit-local-content-through-default-args_hash); full content stays in the local mirror sidecar. |
228
+ | `event_type` | `string` | no | Short name (`'observation'`, `'annotation'`, …) or absolute URI. Default `'observation'`, or derived from `ref.kind` (`'annotates'` → annotation, `'revises'` → revision). An explicit value that contradicts `ref.kind` throws `TypeError`. |
229
+ | `ref` | `AttestRef` | no | Collapsed annotate/revise reference; sets the record's `annotates` or `revises` field. |
230
+ | `informed_by` | `string[]` | no | `sha256:<64-hex>` refs of records this one was informed by ([§1.2.5](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#125-informed_by)). |
231
+ | `allow_unresolved_informed_by` | `boolean` | no | Keep deliberately dangling `informed_by` refs ([D113](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d113-unvalidated-informed_by-refs-are-omitted-by-default) opt-in). |
232
+ | `context_id` | `string` | no | Explicit context (32 lowercase hex). Default: the client's `contextId`, else `resolveEnvContextId()` ([D078](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d078-mcp-servers-honor-atrib_context_id-env-as-context_id-default)/[D083](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d083-harness-session-id-discovery-extends-d078-for-cognitive-primitive-mcp-servers)). |
233
+ | `chain_root` | `string` | no | Explicit chain_root override (requires a context_id). Default: [`resolveChainRoot`](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#1231-multi-producer-chain-composition) precedence in the emit pipeline. |
234
+ | `provenance_token` | `string` | no | [§1.2.6](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#126-provenance_token) cross-session anchor (genesis-only, 22-char base64url). |
235
+ | `tool_name` | `string` | no | [§8.2](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#82-opaque-name-posture) tool-name disclosure. |
236
+ | `args_hash` | `string` | no | Explicit [§8.3](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#83-salted-commitment-posture) args commitment (overrides the [D099](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d099-explicit-emit-records-commit-local-content-through-default-args_hash) default). |
237
+ | `result_hash` | `string` | no | Explicit [§8.3](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#83-salted-commitment-posture) result commitment. |
238
+
239
+ ### `AttestResult`
240
+
241
+ | Field | Type | Meaning |
242
+ | --- | --- | --- |
243
+ | `record_hash` | `string \| null` | `sha256:<64-hex>` of the signed record, or `null` when nothing was signed (degraded). |
244
+ | `context_id` | `string \| null` | Context the record landed in. |
245
+ | `log_index` | `number \| null` | Public-log index when submission already confirmed; `null` while in flight or disabled. |
246
+ | `inclusion_proof` | `ProofBundle['inclusion_proof'] \| null` | RFC 6962 inclusion proof when already available (cached by record hash per [§5.3.5](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#535-log-submission)). |
247
+ | `receipt_id` | `string?` | Present when the emit pipeline issued a receipt id. |
248
+ | `via` | `'daemon' \| 'in-process' \| 'none'` | Which path produced the record. `'none'` = degraded; see `warnings`. |
249
+ | `warnings` | `string[]` | `atrib:`-prefixed operational warnings (anchor skips, fallbacks, pass-through, flush deadline). |
250
+ | `anchor_posture` | `AttestAnchorPosture?` | `{ effective_anchor_count, used_default_set, warned }` — the resolved [§2.11.12](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#21112-producer-side-anchor-posture) posture; present on in-process attests that reached the anchor fan-out. |
251
+ | `attribution_receipt` | `VerifiedAttributionReceipt?` | `{ block, verification }` — the parsed `dev.atrib/attribution` receipt plus its `verifyAttributionReceipt` outcome; only when `attributionReceipts: true` and the daemon emitted one. Advisory. |
252
+
253
+ ### `RecallQuery` shapes
254
+
255
+ `RecallQuery` is the union of ten query interfaces discriminated by
256
+ `shape` (omitted `shape` means `'history'`). `SHAPE_TO_TOOL` maps each
257
+ shape to its physical tool name on the primitives runtime; the fallback
258
+ column says what serves the shape when no daemon is reachable.
259
+
260
+ | Shape | Daemon tool | In-process fallback | Args (beyond `shape`) |
261
+ | --- | --- | --- | --- |
262
+ | `history` (`HistoryQuery`) | `recall_my_attribution_history` | `recall()` from `@atrib/recall` (optional peer) | `context_id?`, `context_scope?` (`'all' \| 'env'`), `creator_key?`, `event_type?`, `content_id?`, `tool_name?`, `args_hash?`, `min_importance?` (`'critical' \| 'high' \| 'medium' \| 'low' \| 'noise'`), `topic_tags?`, `include_revised?`, `min_signers?`, `rank_by?` (`'timestamp' \| 'relevance' \| 'causal_distance'`), `rank_anchor?`, `toc?`, `limit?`, `offset?`, `compact?`, `include_unverified?` |
263
+ | `walk` (`WalkQuery`) | `recall_walk` | none (degrades) | `from_record_hash` (required), `edge_types?` (`'CHAIN_PRECEDES' \| 'INFORMED_BY' \| 'ANNOTATES' \| 'REVISES'`), `depth?` |
264
+ | `annotations` (`AnnotationsQuery`) | `recall_annotations` | none (degrades) | `record_hash` (required) |
265
+ | `revisions` (`RevisionsQuery`) | `recall_revisions` | none (degrades) | `record_hash` (required) |
266
+ | `by_content` (`ByContentQuery`) | `recall_by_content` | none (degrades) | `query` (required), `k?`, `max_records?`, `evidence_mode?` (`'bounded' \| 'require_complete'`) |
267
+ | `session_chain` (`SessionChainQuery`) | `recall_session_chain` | none (degrades) | `context_id?` (defaulted from the client), `limit?`, `include_content?` |
268
+ | `orphans` (`OrphansQuery`) | `recall_orphans` | none (degrades) | `context_id?` (defaulted from the client), `event_type?`, `creator_key?`, `limit?` |
269
+ | `by_signer` (`BySignerQuery`) | `recall_by_signer` | none (degrades) | `min_records?` |
270
+ | `trace` / `trace_forward` (`TraceQuery`) | `trace` / `trace_forward` | none (degrades) | `record_hash` (required), `context_id?`, `depth?`, `max_nodes?`, `compact?`, `include_content?` |
271
+ | `verify` (`VerifyQuery`) | `atrib-verify` | `handleAtribVerify()` from `@atrib/verify-mcp` (optional peer) | `packet?`, `records?`, `claims?`, `required_record_hashes?`, `trusted_creator_keys?`, `allowed_context_ids?`, `require_body?`, `require_body_commitment?`, `require_log_inclusion?`, `log_public_key_b64?`, `now_ms?`, `max_age_ms?` |
272
+
273
+ `verify` is Pattern 3 handoff-claim verification
274
+ ([D105](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d105-pattern-3-handoff-claims-use-verifier-side-claim-acceptance)/[D106](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d106-verify-is-promoted-to-cognitive-primitive-7)).
275
+ "None (degrades)" shapes return `via: 'none'`, `data: null`, and a
276
+ warning naming the runtime tool — honestly, rather than via a divergent
277
+ reimplementation. When a peer-backed fallback engine itself throws, that
278
+ too is caught and degraded.
279
+
280
+ ### `RecallOutcome<T>`
281
+
282
+ | Field | Type | Meaning |
283
+ | --- | --- | --- |
284
+ | `shape` | `RecallShape` | Echo of the resolved shape. |
285
+ | `via` | `'daemon' \| 'in-process' \| 'none'` | Which path served the read. `'none'` = degraded; see `warnings`. |
286
+ | `data` | `T \| null` | The tool/engine result (parsed JSON when the daemon returned the single-JSON-text-block convention), or `null` when degraded. |
287
+ | `warnings` | `string[]` | `atrib:`-prefixed operational warnings. |
288
+ | `attribution_receipt` | `VerifiedAttributionReceipt?` | As on `AttestResult`; opt-in, advisory. |
289
+
290
+ ### `AtribClientConfig`
291
+
292
+ | Field | Type | Default | Meaning |
293
+ | --- | --- | --- | --- |
294
+ | `daemon` | `DaemonConfig` | see below | Daemon endpoint/mode/timeouts. |
295
+ | `anchors` | `AnchorSpec[]` | `BUILT_IN_DEFAULT_ANCHOR_SET` (two anchors; the atrib-log member honors `$ATRIB_LOG_ENDPOINT`) | [D138](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d138-anchor-plurality-as-the-default-trust-posture) anchor set; in-process attests fan out to every member. Hostile entries and unregistered `anchor_type` values warn-and-skip. |
296
+ | `allowSingleAnchor` | `boolean` | `false` | [§2.11.12](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#21112-producer-side-anchor-posture) rule 3: states a < 2-anchor set is deliberate, silencing the sub-plurality warning and the sidecar degradation marker. |
297
+ | `attributionReceipts` | `boolean` | `false` | Opt-in parsing + verification of `dev.atrib/attribution` receipts from daemon `_meta` ([D141](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d141-devatribattribution-first-class-mcp-extension-sep-2133)). |
298
+ | `key` | `ResolvedKey \| null` | `resolveKey()` ladder from `@atrib/emit` (`ATRIB_PRIVATE_KEY` env → `ATRIB_KEY_FILE` → macOS Keychain → 1Password) | Pre-resolved in-process signing key. `null` disables in-process signing (pass-through per [§5.8](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#58-degradation-contract) rule 5). Note: *any* explicitly-set `key` property opts out of the `resolveKey()` ladder. |
299
+ | `contextId` | `string` | `resolveEnvContextId()` at call time | Per-client default context (32 lowercase hex). Context identity stays an explicit per-request value (stateless-MCP-native posture). |
300
+ | `producer` | `string` | `'atrib-sdk'` (`DEFAULT_PRODUCER`) | `_local.producer` mirror-sidecar label ([§5.9](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#59-local-mirror-conventions)); in-process path only. |
301
+
302
+ ### `DaemonConfig` / `DaemonMode`
303
+
304
+ | Field | Type | Default | Meaning |
305
+ | --- | --- | --- | --- |
306
+ | `endpoint` | `string` | `$ATRIB_PRIMITIVES_HTTP_ENDPOINT`, then `http://127.0.0.1:8796/mcp` (`DEFAULT_DAEMON_ENDPOINT`) | MCP Streamable HTTP endpoint of the local primitives runtime. |
307
+ | `mode` | `'prefer' \| 'require' \| 'off'` | `'prefer'` | `'prefer'`: try daemon, fall back in-process. `'require'`: daemon only; failure degrades to a warning result (never a throw). `'off'`: in-process only (no `DaemonClient` is constructed). |
308
+ | `connectTimeoutMs` | `number` | `1500` | Daemon connect timeout. |
309
+ | `callTimeoutMs` | `number` | `10000` | Per-`tools/call` timeout. |
310
+ | `retryCooldownMs` | `number` | `30000` | Cooldown before re-probing an unreachable daemon; within the window, calls skip straight to the fallback. |
311
+
312
+ `resolveDaemonEndpoint(config?)` applies exactly that endpoint
313
+ precedence and is exported for hosts that want to probe the runtime
314
+ themselves.
315
+
316
+ ### `AnchorSpec` / `resolveAnchorSet(anchors, allowSingleAnchor?)` → `ResolvedAnchorSet`
317
+
318
+ An anchor is either a bare string (an atrib-log
319
+ [§2.6.1](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#261-submit-entry)
320
+ endpoint, shorthand for `{ url }`) or an `AnchorDescriptor`
321
+ (`{ anchor_type?, anchor_id?, url?, endpoint?, ... }` — `url` wins over
322
+ `endpoint`; an absent `anchor_type` means `'atrib-log'`; registered
323
+ non-atrib-log types like `'opentimestamps'` need no URL).
324
+
325
+ `resolveAnchorSet` normalizes the caller's specs into the canonical
326
+ [§2.11.12](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#21112-producer-side-anchor-posture)
327
+ `AnchorSetConfig` that `createAnchorFanout` / `resolveAnchorPosture`
328
+ consume, and never throws: hostile entries (non-string/non-object,
329
+ missing/invalid endpoint where one is required) and `anchor_type` values
330
+ outside the [§2.11.8](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#2118-anchor-type-registry)
331
+ registry warn-and-skip — skipped entries are **excluded** from the
332
+ config, so they never count toward the plurality posture. `undefined`
333
+ input returns an empty config (the built-in default set applies
334
+ downstream). Returns `{ config: AnchorSetConfig, primaryLogEndpoint:
335
+ string | undefined, warnings: string[] }`; `primaryLogEndpoint` (the
336
+ first usable atrib-log anchor) doubles as the in-process emit pipeline's
337
+ `logEndpoint`.
338
+
339
+ ### `DaemonClient` / `DaemonCallOutcome`
340
+
341
+ The MCP Streamable HTTP transport to the primitives runtime, exported
342
+ for hosts that want raw tool access with the same degradation posture.
343
+
344
+ ```ts
345
+ new DaemonClient(config?: DaemonConfig, options?: { attributionReceipts?: boolean })
346
+
347
+ type DaemonCallOutcome =
348
+ | { ok: true; value: unknown; attribution?: AttributionReceiptBlock }
349
+ | { ok: false; reason: string }
350
+ ```
351
+
352
+ - `callTool(name, args)` → `Promise<DaemonCallOutcome>`. Never throws.
353
+ Tool results carrying a single JSON text block (the atrib primitive
354
+ convention) are parsed; non-JSON text is returned as the string; other
355
+ result shapes are returned raw. A result with `isError: true` is a
356
+ failure outcome.
357
+ - Connection is lazy and cached; a failed call closes the transport and
358
+ starts the `retryCooldownMs` window, during which `callTool` returns
359
+ `{ ok: false }` immediately without re-probing.
360
+ - `close()` — best-effort transport close; never throws.
361
+ - The client is semantically stateless: `context_id` and chain tokens
362
+ travel as explicit tool arguments on every call; the MCP protocol
363
+ session (initialize handshake + `Mcp-Session-Id`) is a transport
364
+ detail managed by the official `@modelcontextprotocol/sdk` client.
365
+
366
+ ### Hash helpers
367
+
368
+ Compositions of `@atrib/mcp` primitives — no new hashing implementation.
369
+
370
+ | Export | Returns | Meaning |
371
+ | --- | --- | --- |
372
+ | `recordHashHex(record)` | bare 64-char lowercase hex | SHA-256 over the JCS-canonical COMPLETE signed record, including `signature` ([§1.2.3](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#123-chain_root-for-genesis-records)). |
373
+ | `recordHashRef(record)` | `sha256:<64-hex>` | The reference form used by `chain_root`, `informed_by`, `annotates`, `revises`. |
374
+ | `deriveProvenanceToken(upstream)` | 22-char base64url | [§1.2.6](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#126-provenance_token) token for a downstream genesis record: base64url (no padding) of the first 16 bytes of the upstream record hash. |
375
+
376
+ ### Evidence envelope family ([D137](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d137-universal-evidence-envelope-as-the-single-protocol-level-attachment-model), [§5.5.7](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#557-universal-evidence-envelope))
377
+
378
+ Structural types/helpers are SDK-local; envelope **production and
379
+ validation** delegate to the optional peer `@atrib/verify` (lazy import;
380
+ missing peer degrades to a `null` envelope with a warning naming the
381
+ peer — [§5.8](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#58-degradation-contract)).
382
+ Envelopes live outside signed bytes (mirror sidecar, archive evidence
383
+ projection, verifier results, host-owned packets).
384
+
385
+ | Export | Kind | Meaning |
386
+ | --- | --- | --- |
387
+ | `EvidenceTier` | type | `'declared' \| 'shape' \| 'attested' \| 'verified'` — what the verifier party actually did. |
388
+ | `EvidencePayloadRefKind` | type | `'inline' \| 'mirror' \| 'archive' \| 'external' \| 'withheld'`. |
389
+ | `EvidencePayloadRef` | type | `{ kind, uri?, record_hash? }` (`uri` / `record_hash` are string-or-null) — `uri` for archive/external locations; `record_hash` when the payload is itself a signed atrib record. |
390
+ | `EvidencePayload` | type | `{ hash, media_type?, ref?, inline? }` — `hash` is a `"sha256:" + hex` commitment to the raw evidence material; `inline` only when `ref.kind === 'inline'`, never public. The type is lenient; normative validation requires `ref`. |
391
+ | `EvidenceConstraint` | type | `{ type, status: 'passed' \| 'failed' \| 'unresolved' \| 'not_checked', expected?, actual? }`. |
392
+ | `EvidenceEnvelope` | type | `{ envelope: 1, profile, profile_version, tier, payload, facts?, result?, verifier? }` — one envelope schema, N profiles identified by absolute HTTPS type URI. Normative validation requires `result`. |
393
+ | `evidenceEnvelopeKey(envelope)` | function | Dedup identity: `` `${profile} ${payload.hash}` ``. Multiple instances per key are permitted; consumers order by tier desc, then `checked_at_ms` desc, then verifier name. |
394
+ | `evidenceTierRank(tier)` | function | Numeric rank, `0` (declared) … `3` (verified); unknown tiers rank `-1`. |
395
+ | `buildEvidenceEnvelope(input)` | async function | Producer-side builder: computes `payload.hash` from `payload.material` (JCS rule) or `hash_rule: 'raw'` (UTF-8 rule), fills the default `result`, and validates via the peer. Returns `{ envelope, validation, warnings }` with `envelope: null` on rejection or missing peer; throws `TypeError` only on contradictory input (hash AND material, `hash_rule` without material, neither). |
396
+ | `validateEvidenceEnvelope(envelope)` | async function | Runs the peer's normative [§5.5.7](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#557-universal-evidence-envelope) shape validation. Returns `{ validation, warnings }`; `validation: null` when the peer is missing. |
397
+
398
+ ### Attribution receipt family ([D141](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d141-devatribattribution-first-class-mcp-extension-sep-2133), `dev.atrib/attribution` v0.1)
399
+
400
+ Receipts are advisory extension data: trust derives only from verifying
401
+ signed records and inclusion proofs, never from the receipt. See the
402
+ extension document under `docs/extensions/dev.atrib-attribution/`.
403
+
404
+ | Export | Kind | Meaning |
405
+ | --- | --- | --- |
406
+ | `ATTRIBUTION_EXTENSION_KEY` | const | `'dev.atrib/attribution'` — the `_meta` key. Aliases `@atrib/mcp`'s `ATTRIBUTION_EXTENSION_ID` (also re-exported). |
407
+ | `ATTRIBUTION_LOG_SUBMISSION_STATUSES` | const | The four known statuses, re-exported from `@atrib/mcp`. |
408
+ | `AttributionLogSubmissionStatus` | type | `'queued' \| 'submitted' \| 'disabled' \| 'failed'`; unknown future values pass through as strings. A queue status, never an awaited proof ([§5.3.5](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#535-log-submission)). |
409
+ | `AttributionReceipt` | type | `{ record_hash?, creator_key?, context_id?, event_type?, chain_root?, log_submission? }` — all optional strings. |
410
+ | `AttributionReceiptBlock` | type | `{ token?, receipt?, record? }` — the [§1.5.2](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#152-http-transport-tracestate) propagation token, the receipt, and optionally the full signed record for immediate Tier-3 re-verification. |
411
+ | `VerifiedAttributionReceipt` | type | `{ block, verification }` — what the daemon client attaches to attest/recall results: the parsed block plus the [§6.2](https://github.com/creatornader/atrib/blob/main/docs/extensions/dev.atrib-attribution/v0.1.md#62-receipt-block) integrity outcome. |
412
+ | `parseAttributionReceiptBlock(meta)` | function | Lenient extraction from a tool result's `_meta`: anything malformed yields `null`, never a throw; wrong-typed fields are dropped; an all-dropped receipt counts as absent. |
413
+ | `verifyAttributionReceipt(block)` | function | Re-exported from `@atrib/mcp`: the extension-spec [§6.2](https://github.com/creatornader/atrib/blob/main/docs/extensions/dev.atrib-attribution/v0.1.md#62-receipt-block) consumer check over the RAW result block — structural well-formedness plus token ↔ receipt ↔ (optional) record internal consistency. Returns `AttributionReceiptVerification` `{ valid, mismatched }` (`['malformed']` for non-blocks). Internal consistency only; not a proof. |
414
+ | `checkAttributionReceiptConsistency(block, record?)` | function | Record-side consistency: checks a parsed block's claims against the signed record they name (attached or caller-retrieved). No record at all → `{ receipt_valid: false, mismatched_fields: ['record'] }` (conservative, nothing to check against). |
415
+
416
+ ### Record-layer re-exports
417
+
418
+ The complete [§1](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#1-attribution-record-format)
419
+ record layer, re-exported verbatim from `@atrib/mcp` (grouped as in
420
+ `src/index.ts`):
421
+
422
+ **Types + event vocabulary.**
423
+
424
+ - `EVENT_TYPE_TOOL_CALL_URI`, `EVENT_TYPE_TRANSACTION_URI`, `EVENT_TYPE_OBSERVATION_URI`, `EVENT_TYPE_DIRECTORY_ANCHOR_URI`, `EVENT_TYPE_ANNOTATION_URI`, `EVENT_TYPE_REVISION_URI` — the six normative event-type URIs.
425
+ - `EVENT_TYPE_SHORT_NAMES` — the six short aliases accepted by agent-facing tools.
426
+ - `EVENT_TYPE_SHORT_TO_URI` — short alias → canonical URI map.
427
+ - `isNormativeEventTypeUri(uri)` — membership in the normative set (informational).
428
+ - `isValidEventTypeUri(value)` — [§1.4.5](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#145-event_type-uri-validation) syntactic URI validation (extension URIs pass).
429
+ - `normalizeEventType(value)` — short alias / known typo path → canonical URI; unknown values pass through.
430
+
431
+ **Canonicalization ([§1.3](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#13-canonical-serialization)).**
432
+
433
+ - `canonicalRecord(record)` — JCS bytes of the complete signed record (the record-hash preimage).
434
+ - `canonicalSigningInput(record)` — JCS bytes with `signature` removed (the signing input).
435
+ - `canonicalCrossAttestationInput(record)` — [§1.7.6](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#176-cross-attestation-requirement-for-transaction-records) bytes with `signers: []` and no top-level `signature`.
436
+
437
+ **Signing + verification ([§1.4](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#14-signing-and-verification)).**
438
+
439
+ - `getPublicKey(privateKey)` — raw 32-byte Ed25519 public key for a 32-byte seed.
440
+ - `signRecord(record, privateKey)` — [§1.4.2](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#142-signing-procedure) signing; returns the record with `signature` set.
441
+ - `signTransactionRecord(record, privateKey, counterpartySigners?)` — signs the cross-attestation bytes; creator's signer entry first.
442
+ - `signTransactionAttestation(record, privateKey)` — one counterparty `SignerEntry` over an existing transaction record's bytes.
443
+ - `verifyRecord(record)` — [§1.4.3](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#143-verification-procedure) verification, all steps.
444
+
445
+ **Hashing + encoding.**
446
+
447
+ - `sha256(bytes)` — SHA-256 digest.
448
+ - `base64urlEncode` / `base64urlDecode` — base64url, no padding.
449
+ - `hexEncode` / `hexDecode` — lowercase hex.
450
+
451
+ **Chain composition ([§1.2.3](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#123-chain_root-for-genesis-records) / [§1.2.3.1](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#1231-multi-producer-chain-composition)).**
452
+
453
+ - `genesisChainRoot(contextId)` — `"sha256:" + hex(SHA-256(UTF-8(context_id)))`.
454
+ - `chainRoot(parentRecord)` — chain_root for a non-genesis record.
455
+ - `resolveChainRoot(opts)` — the [D067](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d067-multi-producer-chain-composition-precedence-contract) precedence contract (token > autoChain tail > env var > mirror tail > synthetic genesis). Never reimplement chain selection.
456
+
457
+ **Propagation ([§1.5](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#15-context-propagation)).**
458
+
459
+ - `encodeToken(record)` / `decodeToken(token)` — the [§1.5.2](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#152-http-transport-tracestate) propagation token (`base64url(record_hash) + "." + base64url(creator_key)`; lenient decode returns `null`).
460
+ - `extractTraceId(traceparent)` — trace-id from a W3C `traceparent` header.
461
+ - `mergeTracestate(atribEntry, existing)` / `parseTracestateAtrib(tracestate)` — atrib member handling in W3C `tracestate`.
462
+ - `mergeBaggageAtribSession(sessionToken, existing)` / `parseBaggageAtribSession(baggage)` — session token in W3C `baggage`.
463
+ - `readInboundContext(params)` / `writeOutboundContext(...)` — MCP `params._meta` context reading/writing ([§1.5.4](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#154-mcp-transport-params_meta)).
464
+
465
+ **Content identity ([§1.2.2](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#122-content_id-derivation)).**
466
+
467
+ - `computeContentId(serverUrl, toolName)` — `"sha256:" + hex(SHA-256(normalized + ":" + tool))`.
468
+ - `normalizeServerUrl(url)` — WHATWG-semantics URL normalization feeding `content_id`.
469
+
470
+ **Log entry serialization ([§2.3.1](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#231-entry-serialization)).**
471
+
472
+ - `serializeEntry(input)` — the 90-byte fixed log entry.
473
+ - `eventTypeUriToByte(uri)` — event_type byte mapping (extensions → `0xFF`).
474
+
475
+ **Submission-side validation ([§2.6.1](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#261-submit-entry) client parity).**
476
+
477
+ - `validateSubmission(record)` — client-side mirror of the log's submission validation; returns `ValidationResult`.
478
+
479
+ **Mirror conventions ([§5.9](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#59-local-mirror-conventions)).**
480
+
481
+ - `readMirrorTail(...)` — newest record on a mirror file.
482
+ - `inheritChainContext(...)` — mirror-based chain inheritance for new producers.
483
+ - `recordHashExistsInMirror(...)` — presence check by record hash.
484
+
485
+ **Context identity ([D078](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d078-mcp-servers-honor-atrib_context_id-env-as-context_id-default)/[D083](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d083-harness-session-id-discovery-extends-d078-for-cognitive-primitive-mcp-servers)).**
486
+
487
+ - `resolveEnvContextId(env?)` — `ATRIB_CONTEXT_ID`, then the harness discovery registry (Claude Code, Codex, file fallbacks).
488
+
489
+ **Submission queue ([§5.3.5](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#535-log-submission)).**
490
+
491
+ - `createSubmissionQueue(...)` — the non-blocking, bounded-retry log submitter with per-record-hash proof caching.
492
+
493
+ **Type re-exports.** `AtribRecord`, `UnsignedAtribRecord`, `SignerEntry`,
494
+ `ChainContext`, `DecodedToken`, `EntryInput`, `ProofBundle`,
495
+ `SubmissionQueue`, `ValidationResult`.
496
+
497
+ **Anchor plurality ([D138](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d138-anchor-plurality-as-the-default-trust-posture), [§2.11.7-§2.11.13](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#2117-anchors-generalizing-the-replication-target)), re-exported from `@atrib/mcp`.**
498
+
499
+ - `ANCHOR_TYPES` — the [§2.11.8](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#2118-anchor-type-registry) v1 registry (`atrib-log`, `sigstore-rekor`, `rfc3161-tsa`, `opentimestamps`).
500
+ - `BUILT_IN_DEFAULT_ANCHOR_SET` — the two-anchor zero-config default ([§2.11.12](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#21112-producer-side-anchor-posture) rule 1).
501
+ - `resolveAnchorPosture(config)` / `resolveEffectiveAnchors(config)` — the pure [§2.11.12](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#21112-producer-side-anchor-posture) posture/effective-set resolution.
502
+ - `createAnchorFanout(options)` / `submitToAnchors(...)` — the per-anchor transport fan-out the client uses on in-process attests; exported for hosts that anchor records themselves.
503
+ - Types `AnchorType`, `AnchorDescriptor`, `AnchorSetConfig`, `AnchorPostureResolution`, `AnchorConfigSidecarMarker`, `AnchorFanout`, `AnchorFanoutTicket`, `AnchorSubmissionOutcome`, `AnchorSubmissionStatus`.
504
+
505
+ **Key handling ([§5.6](https://github.com/creatornader/atrib/blob/main/atrib-spec.md#56-key-management)), re-exported from `@atrib/emit`.**
506
+
507
+ - `resolveKey()` — the async key ladder: `ATRIB_PRIVATE_KEY` env → `ATRIB_KEY_FILE` → macOS Keychain → 1Password; `null` (pass-through) when nothing resolves.
508
+ - `emitInProcess(input, options?)` — the in-process write engine the SDK's fallback path uses; exported for hosts that want it directly.
509
+ - Types `EmitOutput`, `ResolvedKey`.
510
+
511
+ ## Conformance
512
+
513
+ `test/` runs the shared corpora — `spec/conformance/1.4/` (signing +
514
+ adversarial), `1.2.6/` (provenance_token), `1.2.3/multi-producer/`
515
+ (chain-root precedence), `2.6.1/` (submission validation, client-side),
516
+ `evidence-envelope/` ([D137](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d137-universal-evidence-envelope-as-the-single-protocol-level-attachment-model) shape/build/validate), and the
517
+ `mcp-extension/` receipt cases ([D141](https://github.com/creatornader/atrib/blob/main/DECISIONS.md#d141-devatribattribution-first-class-mcp-extension-sep-2133) `verifyAttributionReceipt` +
518
+ consistency semantics) — against this package's exported surface. The
519
+ corpora are fixtures, not inspiration: any failure is a spec-bug
520
+ discovery, not something to route around.
521
+
522
+ ## Status
523
+
524
+ v0.1.0, unpublished (first-publish pending; see
525
+ `docs/publishing-new-npm-package.md` and the Changesets ignore list).
@@ -0,0 +1,106 @@
1
+ /**
2
+ * attest(): the SDK's single write verb.
3
+ *
4
+ * Collapses emit / annotate / revise under one input shape with an
5
+ * optional `ref` discriminator (redesign upgrade-path step 6). All three
6
+ * routes produce records byte-identical to the existing producers because
7
+ * every path terminates in the same `handleEmit` pipeline:
8
+ *
9
+ * daemon path → tools/call 'emit' on the primitives runtime
10
+ * (the mounted @atrib/emit server; daemon-owned key)
11
+ * in-process path → emitInProcess() from @atrib/emit (caller-owned key)
12
+ *
13
+ * There is deliberately no third signing implementation.
14
+ */
15
+ import type { ProofBundle } from '@atrib/mcp';
16
+ import type { VerifiedAttributionReceipt } from './attribution.js';
17
+ /**
18
+ * The client's resolved D138 anchor posture (§2.11.12), surfaced on
19
+ * in-process attest results. `warned` is true exactly when the config is
20
+ * sub-plurality without `allowSingleAnchor` (rule 4) — the case where the
21
+ * fan-out also produced the §5.9.3 sidecar degradation marker.
22
+ */
23
+ export interface AttestAnchorPosture {
24
+ effective_anchor_count: number;
25
+ used_default_set: boolean;
26
+ warned: boolean;
27
+ }
28
+ /** Reference discriminator collapsing the annotate/revise write kinds. */
29
+ export interface AttestRef {
30
+ kind: 'annotates' | 'revises';
31
+ record_hash: string;
32
+ }
33
+ export interface AttestInput {
34
+ /**
35
+ * The content being attested. Committed via default args_hash
36
+ * (sha256 of JCS(content)) per D099; full content stays in the local
37
+ * mirror sidecar.
38
+ */
39
+ content: Record<string, unknown>;
40
+ /**
41
+ * Event type short name ('observation', 'annotation', …) or absolute
42
+ * URI. Default 'observation', or derived from `ref.kind` when a ref is
43
+ * present ('annotates' → annotation, 'revises' → revision).
44
+ */
45
+ event_type?: string;
46
+ /** Collapsed annotate/revise reference (sets annotates/revises field). */
47
+ ref?: AttestRef;
48
+ /** sha256:<64-hex> refs of records this one was informed by. */
49
+ informed_by?: string[];
50
+ /** Keep deliberately dangling informed_by refs (D113 opt-in). */
51
+ allow_unresolved_informed_by?: boolean;
52
+ /** Explicit context_id (32 lowercase hex). */
53
+ context_id?: string;
54
+ /** Explicit chain_root override (requires context_id). */
55
+ chain_root?: string;
56
+ /** §1.2.6 cross-session anchor (genesis-only, 22-char base64url). */
57
+ provenance_token?: string;
58
+ /** §8.2 tool-name disclosure. */
59
+ tool_name?: string;
60
+ /** Explicit §8.3 args commitment (overrides the D099 default). */
61
+ args_hash?: string;
62
+ /** Explicit §8.3 result commitment. */
63
+ result_hash?: string;
64
+ }
65
+ export interface AttestResult {
66
+ /** `sha256:<64-hex>` of the signed record, or null when nothing signed. */
67
+ record_hash: string | null;
68
+ context_id: string | null;
69
+ log_index: number | null;
70
+ inclusion_proof: ProofBundle['inclusion_proof'] | null;
71
+ receipt_id?: string;
72
+ /** Which path produced the record. 'none' = degraded, see warnings. */
73
+ via: 'daemon' | 'in-process' | 'none';
74
+ warnings: string[];
75
+ /**
76
+ * `dev.atrib/attribution` receipt from the daemon result's `_meta`,
77
+ * present only when `attributionReceipts` is enabled and the daemon
78
+ * emitted one (D141): the parsed block plus its
79
+ * `verifyAttributionReceipt` outcome. Advisory; trust derives from
80
+ * verifying signed records.
81
+ */
82
+ attribution_receipt?: VerifiedAttributionReceipt;
83
+ /**
84
+ * D138 anchor posture of the client's fan-out (§2.11.12), present on
85
+ * in-process results after anchor fan-out was consulted. The daemon
86
+ * path never carries it: the daemon owns its own anchors.
87
+ */
88
+ anchor_posture?: AttestAnchorPosture;
89
+ }
90
+ /**
91
+ * Map AttestInput to the EmitInput argument shape shared by the daemon's
92
+ * `emit` tool and `emitInProcess`. Throws TypeError on contradictory input
93
+ * (the only throw path of the write verb — operational failures degrade).
94
+ */
95
+ export declare function buildEmitArgs(input: AttestInput, defaultContextId?: string): Record<string, unknown>;
96
+ /** Shape of the daemon `emit` tool's JSON result (EmitOutput). */
97
+ export interface EmitOutputLike {
98
+ record_hash?: unknown;
99
+ log_index?: unknown;
100
+ inclusion_proof?: unknown;
101
+ context_id?: unknown;
102
+ receipt_id?: unknown;
103
+ warnings?: unknown;
104
+ }
105
+ export declare function attestResultFromEmitOutput(output: EmitOutputLike, via: 'daemon' | 'in-process', extraWarnings: string[]): AttestResult;
106
+ //# sourceMappingURL=attest.d.ts.map