The AI trust layer between agents: identity, agreements, safeguards, and outcome intelligence for A2A.

Viewing files at commit 4818f40a6317Commit detailsView latest

tests/source-record.test.ts 93 lines · 3.5 KB · typescript
1
import { describe, expect, it } from 'vitest';
2
import {
3
  HOSTED_MIGRATIONS,
4
  buildSourceRecordEnvelope,
5
  shouldJournalSourceRecord,
6
} from '@openclasp/persistence';
7
import { SourceRecordEnvelopeSchema, canonicalHash } from '@openclasp/protocol';
8
9
describe('production source record journal', () => {
10
  it('wraps a hosted record with explicit lineage and stable content integrity', () => {
11
    const payload = {
12
      interactionId: '11111111-1111-4111-8111-111111111111',
13
      agentId: 'agent:provider',
14
      outcome: 'success',
15
      completedAt: '2026-08-31T10:15:00.000Z',
16
      contributionMode: 'local_only',
17
    };
18
    const source = buildSourceRecordEnvelope({
19
      operatorId: 'operator:buyer',
20
      kind: 'completion_report',
21
      recordId: 'report:1',
22
      payload,
23
      metadata: {
24
        eventId: '22222222-2222-4222-8222-222222222222',
25
        ingestedAt: '2026-08-31T10:16:00.000Z',
26
      },
27
    });
28
29
    expect(SourceRecordEnvelopeSchema.parse(source)).toEqual(source);
30
    expect(source.payloadDigest).toBe(canonicalHash(payload));
31
    expect(source.reportedAt).toBe(payload.completedAt);
32
    expect(source.ingestedAt).toBe('2026-08-31T10:16:00.000Z');
33
    expect(source.entityRefs).toEqual({
34
      agentId: 'agent:provider',
35
      interactionId: payload.interactionId,
36
    });
37
    expect(source.learningScope).toBe('local_only');
38
    expect(source.retentionClass).toBe('audit');
39
    expect(source.provenance).toBe('observed');
40
    expect(source.visibility).toBe('shared_participants');
41
  });
42
43
  it('uses canonical payload digests and permits explicit collection metadata', () => {
44
    const base = {
45
      operatorId: 'operator:one',
46
      kind: 'agent_profile',
47
      recordId: 'agent:one',
48
      metadata: {
49
        eventId: '33333333-3333-4333-8333-333333333333',
50
        reportedAt: '2026-08-31T00:00:00.000Z',
51
        ingestedAt: '2026-08-31T00:00:01.000Z',
52
        provenance: 'operator_attested' as const,
53
        visibility: 'shared_participants' as const,
54
        entityRefs: { deploymentId: 'deployment:one' },
55
      },
56
    };
57
    const left = buildSourceRecordEnvelope({ ...base, payload: { b: 2, a: 1 } });
58
    const right = buildSourceRecordEnvelope({ ...base, payload: { a: 1, b: 2 } });
59
60
    expect(left.payloadDigest).toBe(right.payloadDigest);
61
    expect(left.retentionClass).toBe('account');
62
    expect(left.provenance).toBe('operator_attested');
63
    expect(left.visibility).toBe('shared_participants');
64
    expect(left.entityRefs.deploymentId).toBe('deployment:one');
65
  });
66
67
  it('rejects values that cannot be retained as JSON', () => {
68
    expect(() =>
69
      buildSourceRecordEnvelope({
70
        operatorId: 'operator:one',
71
        kind: 'event',
72
        recordId: 'event:one',
73
        payload: { invalid: undefined },
74
      }),
75
    ).toThrow();
76
  });
77
78
  it('keeps hosted migrations numbered, ordered, and uniquely named', () => {
79
    expect(HOSTED_MIGRATIONS.map((migration) => migration.version)).toEqual([1, 2]);
80
    expect(new Set(HOSTED_MIGRATIONS.map((migration) => migration.name)).size).toBe(
81
      HOSTED_MIGRATIONS.length,
82
    );
83
  });
84
85
  it('journals intelligence inputs but not high-volume operational projections', () => {
86
    expect(shouldJournalSourceRecord('completion_report')).toBe(true);
87
    expect(shouldJournalSourceRecord('interaction_feedback')).toBe(true);
88
    expect(shouldJournalSourceRecord('profile_delta')).toBe(true);
89
    expect(shouldJournalSourceRecord('presence')).toBe(false);
90
    expect(shouldJournalSourceRecord('profile')).toBe(false);
91
    expect(shouldJournalSourceRecord('feedback_request')).toBe(false);
92
  });
93
});