@atrib/attest 0.2.0 → 0.3.1
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 +6 -0
- package/dist/attest.js +1 -2
- package/dist/index.d.ts +29 -2
- package/dist/index.js +31 -17
- package/dist/reference-resolution.d.ts +1 -0
- package/dist/reference-resolution.js +3 -1
- package/dist/storage.d.ts +2 -1
- package/dist/storage.js +5 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -146,6 +146,12 @@ Environment variables are unchanged from the legacy emit surface:
|
|
|
146
146
|
table with descriptions; the values and resolution order carried over
|
|
147
147
|
unchanged.
|
|
148
148
|
|
|
149
|
+
Programmatic callers can set `mirrorPath` and `autochainSource` in
|
|
150
|
+
`EmitInProcessOptions`. `mirrorPath` selects the write target for one call.
|
|
151
|
+
`autochainSource` selects its mirror-based chain inheritance source. When only
|
|
152
|
+
`mirrorPath` is set, it is also the read source. Calls that omit both options
|
|
153
|
+
retain the environment and per-agent default ladder above.
|
|
154
|
+
|
|
149
155
|
## Degradation and privacy
|
|
150
156
|
|
|
151
157
|
atrib failures never affect the primary call ([spec §5.8](../../atrib-spec.md#58-degradation-contract)), and for the write
|
package/dist/attest.js
CHANGED
|
@@ -86,9 +86,8 @@ export const AttestInput = z.object({
|
|
|
86
86
|
tool_name: z
|
|
87
87
|
.string()
|
|
88
88
|
.min(1)
|
|
89
|
-
.max(64)
|
|
90
89
|
.optional()
|
|
91
|
-
.describe('Optional §8.2 tool_name disclosure
|
|
90
|
+
.describe('Optional §8.2 tool_name disclosure. The 64-character cap applies only to opaque labels; hashed and verbatim forms follow §8.2.'),
|
|
92
91
|
args_hash: z
|
|
93
92
|
.string()
|
|
94
93
|
.regex(SHA256_REF_PATTERN)
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { z } from 'zod';
|
|
|
3
3
|
import { type LocalSubstrateCoordinatorTransport, type LocalSubstrateDegradationPolicy, type LocalSubstrateHarnessClass, type LocalSubstrateProducer, type LocalSubstrateWalJoin, type ProofBundle, type SubmissionQueue, type TryLocalSubstrateCoordinatorResult } from '@atrib/mcp';
|
|
4
4
|
import { type ResolvedKey } from './keys.js';
|
|
5
5
|
import { type RecordReferenceResolver } from './reference-resolution.js';
|
|
6
|
+
import { resolveMirrorWritePath } from './storage.js';
|
|
6
7
|
import { type AttestInputT } from './attest.js';
|
|
7
8
|
declare function keyResolveRetryMs(): number;
|
|
8
9
|
export declare function requiresExplicitContextId(env?: NodeJS.ProcessEnv): boolean;
|
|
@@ -175,7 +176,7 @@ declare function createServerKeyResolver(options: CreateAtribEmitServerOptions):
|
|
|
175
176
|
interface HandleEmitInput {
|
|
176
177
|
input: z.infer<typeof EmitInput>;
|
|
177
178
|
key: ResolvedKey | null;
|
|
178
|
-
queue
|
|
179
|
+
queue?: SubmissionQueue;
|
|
179
180
|
/**
|
|
180
181
|
* Producer label written to the sidecar's `_local.producer` field for
|
|
181
182
|
* cross-source disambiguation in mirror queries. Defaults to
|
|
@@ -185,6 +186,13 @@ interface HandleEmitInput {
|
|
|
185
186
|
*/
|
|
186
187
|
producer?: string;
|
|
187
188
|
logEndpoint?: string | undefined;
|
|
189
|
+
/** Explicit write target for this call. Falls back to ATRIB_MIRROR_FILE. */
|
|
190
|
+
mirrorPath?: string | undefined;
|
|
191
|
+
/**
|
|
192
|
+
* Explicit read source for mirror-based chain inheritance. When omitted,
|
|
193
|
+
* mirrorPath wins before the legacy environment and default path ladder.
|
|
194
|
+
*/
|
|
195
|
+
autochainSource?: string | undefined;
|
|
188
196
|
recordReferenceResolver?: RecordReferenceResolver | undefined;
|
|
189
197
|
localSubstrate?: EmitLocalSubstrateShadowOptions | undefined;
|
|
190
198
|
localSubstrateCommit?: EmitLocalSubstrateCommitOptions | undefined;
|
|
@@ -193,7 +201,7 @@ interface HandleEmitInput {
|
|
|
193
201
|
* Build, sign, submit, mirror. Refused writes return `signed: false`;
|
|
194
202
|
* signed degradations stay `signed: true` and surface in `warnings`.
|
|
195
203
|
*/
|
|
196
|
-
declare function handleEmit({ input, key, queue, producer, logEndpoint, recordReferenceResolver, localSubstrate, localSubstrateCommit, }: HandleEmitInput): Promise<EmitOutput>;
|
|
204
|
+
declare function handleEmit({ input, key, queue, producer, logEndpoint, mirrorPath, autochainSource, recordReferenceResolver, localSubstrate, localSubstrateCommit, }: HandleEmitInput): Promise<EmitOutput>;
|
|
197
205
|
export declare function resolveEmitLocalSubstrateShadowFromEnv(options?: ResolveEmitLocalSubstrateShadowFromEnvOptions): EmitLocalSubstrateShadowOptions | undefined;
|
|
198
206
|
export declare function resolveEmitLocalSubstrateCommitFromEnv(options?: ResolveEmitLocalSubstrateCommitFromEnvOptions): EmitLocalSubstrateCommitOptions | undefined;
|
|
199
207
|
export interface EmitInProcessOptions {
|
|
@@ -201,6 +209,11 @@ export interface EmitInProcessOptions {
|
|
|
201
209
|
key?: ResolvedKey;
|
|
202
210
|
/** Override the log endpoint (defaults to ATRIB_LOG_ENDPOINT or @atrib/mcp default). */
|
|
203
211
|
logEndpoint?: string | undefined;
|
|
212
|
+
/**
|
|
213
|
+
* Set false for local-only producers. The record is still signed and
|
|
214
|
+
* mirrored, but this process does not create a public-log queue.
|
|
215
|
+
*/
|
|
216
|
+
submit?: boolean;
|
|
204
217
|
/**
|
|
205
218
|
* Producer label written to the sidecar's `_local.producer` field for
|
|
206
219
|
* cross-source disambiguation. Defaults to `'atrib-emit'`. Callers that
|
|
@@ -210,6 +223,17 @@ export interface EmitInProcessOptions {
|
|
|
210
223
|
* consumers can bucket records by emitter without inspecting envelopes.
|
|
211
224
|
*/
|
|
212
225
|
producer?: string;
|
|
226
|
+
/**
|
|
227
|
+
* Explicit mirror write target for this call. When omitted,
|
|
228
|
+
* ATRIB_MIRROR_FILE and the per-agent default remain unchanged fallbacks.
|
|
229
|
+
*/
|
|
230
|
+
mirrorPath?: string | undefined;
|
|
231
|
+
/**
|
|
232
|
+
* Explicit mirror read source for chain inheritance. When omitted, an
|
|
233
|
+
* explicit mirrorPath is also the read source before the environment
|
|
234
|
+
* fallback ladder.
|
|
235
|
+
*/
|
|
236
|
+
autochainSource?: string | undefined;
|
|
213
237
|
/**
|
|
214
238
|
* Upper bound on the post-sign queue flush, in milliseconds. Default
|
|
215
239
|
* 5000ms. The submission queue itself has a 30s retry budget against an
|
|
@@ -277,6 +301,8 @@ export interface HandleAttestInput {
|
|
|
277
301
|
/** Sidecar label; defaults to 'atrib-attest'. input.producer wins. */
|
|
278
302
|
producer?: string;
|
|
279
303
|
logEndpoint?: string | undefined;
|
|
304
|
+
mirrorPath?: string | undefined;
|
|
305
|
+
autochainSource?: string | undefined;
|
|
280
306
|
recordReferenceResolver?: RecordReferenceResolver | undefined;
|
|
281
307
|
localSubstrate?: EmitLocalSubstrateShadowOptions | undefined;
|
|
282
308
|
localSubstrateCommit?: EmitLocalSubstrateCommitOptions | undefined;
|
|
@@ -301,6 +327,7 @@ export declare const __test_only__: {
|
|
|
301
327
|
keyResolveRetryMs: typeof keyResolveRetryMs;
|
|
302
328
|
};
|
|
303
329
|
export { handleEmit, EmitInput };
|
|
330
|
+
export { resolveMirrorWritePath };
|
|
304
331
|
export type { EmitOutput };
|
|
305
332
|
export { resolveKey } from './keys.js';
|
|
306
333
|
export type { ResolvedKey } from './keys.js';
|
package/dist/index.js
CHANGED
|
@@ -17,13 +17,11 @@
|
|
|
17
17
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
18
18
|
import { z } from 'zod';
|
|
19
19
|
import { randomBytes } from 'node:crypto';
|
|
20
|
-
import { homedir } from 'node:os';
|
|
21
|
-
import { join } from 'node:path';
|
|
22
20
|
import { EVENT_TYPE_ANNOTATION_URI, EVENT_TYPE_REVISION_URI, LOCAL_SUBSTRATE_DEFAULT_TIMEOUT_MS, LOCAL_SUBSTRATE_REQUEST_SCHEMA, canonicalRecord, createHttpLocalSubstrateTransport, createSubmissionQueue, genesisChainRoot, hexEncode, inheritChainContext, isValidEventTypeUri, normalizeEventType, parentRecordHashFromEnv, resolveEnvContextId, SHA256_REF_PATTERN, sha256, tryLocalSubstrateCoordinator, } from '@atrib/mcp';
|
|
23
21
|
import { resolveKey } from './keys.js';
|
|
24
22
|
import { filterResolvableInformedBy } from './reference-resolution.js';
|
|
25
23
|
import { buildAndSignEmitRecord } from './sign.js';
|
|
26
|
-
import { mirrorRecord } from './storage.js';
|
|
24
|
+
import { mirrorRecord, resolveMirrorWritePath } from './storage.js';
|
|
27
25
|
import { AttestInput, isAttestMappingRefusal, mapAttestInput } from './attest.js';
|
|
28
26
|
import { registerAnnotateTool } from './annotate.js';
|
|
29
27
|
import { registerReviseTool } from './revise.js';
|
|
@@ -33,10 +31,11 @@ import { registerReviseTool } from './revise.js';
|
|
|
33
31
|
// rarely useful as a read source, but kept for backward compatibility),
|
|
34
32
|
// then to the per-agent default. Distinct from ATRIB_MIRROR_FILE which is
|
|
35
33
|
// where emit's own records are persisted.
|
|
36
|
-
function readMirrorPath() {
|
|
37
|
-
return (
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
function readMirrorPath(options = {}) {
|
|
35
|
+
return (options.autochainSource ??
|
|
36
|
+
options.mirrorPath ??
|
|
37
|
+
process.env['ATRIB_AUTOCHAIN_SOURCE'] ??
|
|
38
|
+
resolveMirrorWritePath());
|
|
40
39
|
}
|
|
41
40
|
const HEX_32_PATTERN = /^[0-9a-f]{32}$/;
|
|
42
41
|
// 16 bytes encoded as base64url with no padding = 22 chars per spec §1.2.6.
|
|
@@ -127,10 +126,11 @@ const EmitInput = z.object({
|
|
|
127
126
|
tool_name: z
|
|
128
127
|
.string()
|
|
129
128
|
.min(1)
|
|
130
|
-
.max(64)
|
|
131
129
|
.optional()
|
|
132
130
|
.describe('Optional §8.2 tool_name disclosure. Verbatim or transformed name (verbatim, opaque, ' +
|
|
133
|
-
'or hashed per §8.2).
|
|
131
|
+
'or hashed per §8.2). The 64-character cap applies only to opaque-label form; ' +
|
|
132
|
+
'the hashed form is sha256:<64 lowercase hex>, and verbatim names have no ' +
|
|
133
|
+
'protocol-wide length cap. Lets emit-signed records carry the tool name for downstream ' +
|
|
134
134
|
'consumers (e.g. recall_my_attribution_history filtering by tool_name). Absence ' +
|
|
135
135
|
'indicates the §8.1 default posture (no disclosure).'),
|
|
136
136
|
args_hash: z
|
|
@@ -339,7 +339,7 @@ function createServerKeyResolver(options) {
|
|
|
339
339
|
* Build, sign, submit, mirror. Refused writes return `signed: false`;
|
|
340
340
|
* signed degradations stay `signed: true` and surface in `warnings`.
|
|
341
341
|
*/
|
|
342
|
-
async function handleEmit({ input, key, queue, producer, logEndpoint, recordReferenceResolver, localSubstrate, localSubstrateCommit, }) {
|
|
342
|
+
async function handleEmit({ input, key, queue, producer, logEndpoint, mirrorPath, autochainSource, recordReferenceResolver, localSubstrate, localSubstrateCommit, }) {
|
|
343
343
|
const warnings = [];
|
|
344
344
|
const eventType = normalizeEventType(input.event_type);
|
|
345
345
|
if (!isValidEventTypeUri(eventType)) {
|
|
@@ -430,10 +430,14 @@ async function handleEmit({ input, key, queue, producer, logEndpoint, recordRefe
|
|
|
430
430
|
// is the primary case that needs preserving; pre-fix this produced isolated
|
|
431
431
|
// genesis records because atrib-emit's local resolver short-circuited on
|
|
432
432
|
// caller context.
|
|
433
|
+
const autochainMirrorPath = readMirrorPath({ autochainSource, mirrorPath });
|
|
433
434
|
const chain = await inheritChainContext({
|
|
434
435
|
callerContextId,
|
|
435
436
|
callerChainRoot: input.chain_root,
|
|
436
|
-
mirrorPath:
|
|
437
|
+
mirrorPath: autochainMirrorPath,
|
|
438
|
+
...((mirrorPath !== undefined || autochainSource !== undefined) && {
|
|
439
|
+
mirrorScope: 'file',
|
|
440
|
+
}),
|
|
437
441
|
randomContextId,
|
|
438
442
|
});
|
|
439
443
|
const contextId = chain.contextId;
|
|
@@ -464,6 +468,9 @@ async function handleEmit({ input, key, queue, producer, logEndpoint, recordRefe
|
|
|
464
468
|
allowUnresolved: input.allow_unresolved_informed_by,
|
|
465
469
|
resolver: recordReferenceResolver,
|
|
466
470
|
logEndpoint,
|
|
471
|
+
...((mirrorPath !== undefined || autochainSource !== undefined) && {
|
|
472
|
+
localMirrorPaths: [resolveMirrorWritePath(mirrorPath), autochainMirrorPath],
|
|
473
|
+
}),
|
|
467
474
|
warnings,
|
|
468
475
|
});
|
|
469
476
|
const effectiveInformedBy = validParentHash
|
|
@@ -528,7 +535,7 @@ async function handleEmit({ input, key, queue, producer, logEndpoint, recordRefe
|
|
|
528
535
|
// Submit asynchronously; the queue handles retry + degradation per §5.8.
|
|
529
536
|
// Cognitive events default to normal priority, annotations/observations
|
|
530
537
|
// never need to block the agent.
|
|
531
|
-
if (!localSubstrateCommitted) {
|
|
538
|
+
if (!localSubstrateCommitted && queue) {
|
|
532
539
|
queue.submit(record, 'normal');
|
|
533
540
|
}
|
|
534
541
|
// Best-effort mirror; mirrorRecord internally swallows errors per §5.8.
|
|
@@ -539,7 +546,7 @@ async function handleEmit({ input, key, queue, producer, logEndpoint, recordRefe
|
|
|
539
546
|
await mirrorRecord(record, getProofFor(queue, recordHash) ?? null, {
|
|
540
547
|
content: input.content,
|
|
541
548
|
producer: producer ?? 'atrib-emit',
|
|
542
|
-
});
|
|
549
|
+
}, mirrorPath);
|
|
543
550
|
// Try to read a proof if the queue submitted synchronously and the log
|
|
544
551
|
// returned one within the same tick. Most submissions return null here
|
|
545
552
|
// and the proof shows up on a later poll via getProof.
|
|
@@ -547,7 +554,7 @@ async function handleEmit({ input, key, queue, producer, logEndpoint, recordRefe
|
|
|
547
554
|
if (!proof && localSubstrateCommitted) {
|
|
548
555
|
warnings.push('submission delegated to local substrate coordinator; proof not available in this process');
|
|
549
556
|
}
|
|
550
|
-
else if (!proof) {
|
|
557
|
+
else if (!proof && queue) {
|
|
551
558
|
warnings.push('submission queued; proof not yet available (poll the log later if needed)');
|
|
552
559
|
}
|
|
553
560
|
if (localSubstrate?.waitForAttempt && localSubstrateShadow) {
|
|
@@ -874,6 +881,8 @@ function notifyLocalSubstrateWarning(localSubstrate, message, detail) {
|
|
|
874
881
|
* warning, even when the record had already landed on the log.
|
|
875
882
|
*/
|
|
876
883
|
function getProofFor(queue, recordHash) {
|
|
884
|
+
if (!queue)
|
|
885
|
+
return undefined;
|
|
877
886
|
return queue.getProof(recordHash.startsWith('sha256:') ? recordHash.slice('sha256:'.length) : recordHash);
|
|
878
887
|
}
|
|
879
888
|
const DEFAULT_FLUSH_DEADLINE_MS = 5000;
|
|
@@ -910,13 +919,15 @@ export async function emitInProcess(rawInput, options = {}) {
|
|
|
910
919
|
const key = options.key ?? (await resolveKey());
|
|
911
920
|
const logEndpoint = options.logEndpoint ?? process.env['ATRIB_LOG_ENDPOINT'];
|
|
912
921
|
const flushDeadlineMs = options.flushDeadlineMs ?? DEFAULT_FLUSH_DEADLINE_MS;
|
|
913
|
-
const queue = createSubmissionQueue(logEndpoint);
|
|
922
|
+
const queue = options.submit === false ? undefined : createSubmissionQueue(logEndpoint);
|
|
914
923
|
const result = await handleEmit({
|
|
915
924
|
input,
|
|
916
925
|
key,
|
|
917
|
-
queue,
|
|
926
|
+
...(queue !== undefined ? { queue } : {}),
|
|
918
927
|
producer: options.producer,
|
|
919
928
|
logEndpoint,
|
|
929
|
+
mirrorPath: options.mirrorPath,
|
|
930
|
+
autochainSource: options.autochainSource,
|
|
920
931
|
recordReferenceResolver: options.recordReferenceResolver,
|
|
921
932
|
localSubstrate: resolveLocalSubstrateOption(options.localSubstrate, {
|
|
922
933
|
producer: options.producer ?? 'atrib-emit',
|
|
@@ -932,7 +943,7 @@ export async function emitInProcess(rawInput, options = {}) {
|
|
|
932
943
|
transport: 'emit-in-process',
|
|
933
944
|
}),
|
|
934
945
|
});
|
|
935
|
-
if (!result.signed) {
|
|
946
|
+
if (!result.signed || queue === undefined) {
|
|
936
947
|
return result;
|
|
937
948
|
}
|
|
938
949
|
// Drain before returning, bounded by flushDeadlineMs. The typical caller
|
|
@@ -979,6 +990,8 @@ export async function handleAttest(args) {
|
|
|
979
990
|
queue: args.queue,
|
|
980
991
|
producer: args.input.producer ?? args.producer ?? 'atrib-attest',
|
|
981
992
|
logEndpoint: args.logEndpoint,
|
|
993
|
+
mirrorPath: args.mirrorPath,
|
|
994
|
+
autochainSource: args.autochainSource,
|
|
982
995
|
recordReferenceResolver: args.recordReferenceResolver,
|
|
983
996
|
localSubstrate: args.localSubstrate,
|
|
984
997
|
localSubstrateCommit: args.localSubstrateCommit,
|
|
@@ -1025,6 +1038,7 @@ export const __test_only__ = { createServerKeyResolver, handleEmit, keyResolveRe
|
|
|
1025
1038
|
//
|
|
1026
1039
|
// Stable as of @atrib/emit@0.8.0. Breaking changes here require a major bump.
|
|
1027
1040
|
export { handleEmit, EmitInput };
|
|
1041
|
+
export { resolveMirrorWritePath };
|
|
1028
1042
|
export { resolveKey } from './keys.js';
|
|
1029
1043
|
// Session-checkpoint emission (§1.2.10 / D139): reads the ordered record
|
|
1030
1044
|
// hashes for a context from the local mirror per §5.9 and emits the
|
|
@@ -4,6 +4,7 @@ interface FilterResolvableInformedByOptions {
|
|
|
4
4
|
allowUnresolved?: boolean | undefined;
|
|
5
5
|
resolver?: RecordReferenceResolver | undefined;
|
|
6
6
|
logEndpoint?: string | undefined;
|
|
7
|
+
localMirrorPaths?: readonly string[] | undefined;
|
|
7
8
|
warnings: string[];
|
|
8
9
|
}
|
|
9
10
|
export declare const defaultRecordReferenceResolver: typeof sharedDefaultRecordReferenceResolver;
|
|
@@ -8,7 +8,9 @@ export async function filterResolvableInformedBy(refs, options) {
|
|
|
8
8
|
return unique;
|
|
9
9
|
const kept = [];
|
|
10
10
|
const resolver = options.resolver ??
|
|
11
|
-
((recordHash) => defaultRecordReferenceResolver(recordHash, options.logEndpoint
|
|
11
|
+
((recordHash) => defaultRecordReferenceResolver(recordHash, options.logEndpoint, {
|
|
12
|
+
localMirrorPaths: options.localMirrorPaths,
|
|
13
|
+
}));
|
|
12
14
|
for (const ref of unique) {
|
|
13
15
|
const resolution = await resolver(ref);
|
|
14
16
|
if (resolution === 'found') {
|
package/dist/storage.d.ts
CHANGED
|
@@ -18,10 +18,11 @@ export interface MirrorLine {
|
|
|
18
18
|
/** Optional local-only sidecar; absent on legacy entries. */
|
|
19
19
|
_local?: LocalSidecar;
|
|
20
20
|
}
|
|
21
|
+
export declare function resolveMirrorWritePath(explicitPath?: string): string;
|
|
21
22
|
/**
|
|
22
23
|
* Append one record + optional proof + optional local sidecar to the
|
|
23
24
|
* mirror file. Failures log with the atrib-emit prefix and otherwise
|
|
24
25
|
* no-op, per §5.8 the mirror is best-effort and never blocks the
|
|
25
26
|
* agent.
|
|
26
27
|
*/
|
|
27
|
-
export declare function mirrorRecord(record: AtribRecord, proof: ProofBundle | null, localSidecar?: LocalSidecar): Promise<void>;
|
|
28
|
+
export declare function mirrorRecord(record: AtribRecord, proof: ProofBundle | null, localSidecar?: LocalSidecar, explicitPath?: string): Promise<void>;
|
package/dist/storage.js
CHANGED
|
@@ -30,8 +30,9 @@ import { appendFile, mkdir } from 'node:fs/promises';
|
|
|
30
30
|
import { homedir } from 'node:os';
|
|
31
31
|
import { dirname, join } from 'node:path';
|
|
32
32
|
let ensuredDirs = new Set();
|
|
33
|
-
function
|
|
34
|
-
return (
|
|
33
|
+
export function resolveMirrorWritePath(explicitPath) {
|
|
34
|
+
return (explicitPath ??
|
|
35
|
+
process.env['ATRIB_MIRROR_FILE'] ??
|
|
35
36
|
join(homedir(), '.atrib', 'records', `atrib-emit-${process.env['ATRIB_AGENT'] ?? 'claude-code'}.jsonl`));
|
|
36
37
|
}
|
|
37
38
|
/**
|
|
@@ -40,8 +41,8 @@ function mirrorPath() {
|
|
|
40
41
|
* no-op, per §5.8 the mirror is best-effort and never blocks the
|
|
41
42
|
* agent.
|
|
42
43
|
*/
|
|
43
|
-
export async function mirrorRecord(record, proof, localSidecar) {
|
|
44
|
-
const path =
|
|
44
|
+
export async function mirrorRecord(record, proof, localSidecar, explicitPath) {
|
|
45
|
+
const path = resolveMirrorWritePath(explicitPath);
|
|
45
46
|
const line = { record, proof, written_at: Date.now() };
|
|
46
47
|
if (localSidecar) {
|
|
47
48
|
line._local = localSidecar;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atrib/attest",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "MCP server for atrib's write verb. One attest tool signs observations, annotations, and revisions; the legacy emit, atrib-annotate, and atrib-revise tool names stay mounted as aliases over the same handler.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"atrib",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@noble/hashes": "^2.2.0",
|
|
46
46
|
"canonicalize": "^3.0.0",
|
|
47
47
|
"zod": "^3.25.76",
|
|
48
|
-
"@atrib/mcp": "0.
|
|
48
|
+
"@atrib/mcp": "0.23.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^26.1.1",
|