@adastracomputing/ink 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +63 -0
- package/CODE_OF_CONDUCT.md +42 -0
- package/LICENSE-APACHE +201 -0
- package/LICENSE-MIT +21 -0
- package/README.md +133 -0
- package/SECURITY.md +57 -0
- package/docs/key-rotation-rule.md +108 -0
- package/docs/logo.svg +8 -0
- package/docs/maturity.md +81 -0
- package/docs/threat-model.md +150 -0
- package/package.json +72 -0
- package/specs/ink-agent-containment-and-governance-extension-spec.md +508 -0
- package/specs/ink-auditability.md +652 -0
- package/specs/ink-authorization-chain.md +242 -0
- package/specs/ink-compatibility-policy.md +263 -0
- package/specs/ink-compliance-checklist.md +309 -0
- package/specs/ink-containment-phase1-implementation-spec.md +593 -0
- package/specs/ink-introduction-receipts-extension.md +501 -0
- package/specs/ink-key-rotation-spec.md +535 -0
- package/src/crypto/ink.ts +902 -0
- package/src/crypto/keys.ts +211 -0
- package/src/crypto/multi-key-verify.ts +170 -0
- package/src/crypto/sign.ts +155 -0
- package/src/crypto/verify.ts +1 -0
- package/src/discovery/agent-card.ts +508 -0
- package/src/index.ts +59 -0
- package/src/ink/checkpoint.ts +75 -0
- package/src/ink/discovery-gating.ts +147 -0
- package/src/ink/handshake-budget.ts +413 -0
- package/src/ink/receipts.ts +114 -0
- package/src/ink/transport-auth.ts +96 -0
- package/src/middleware/ink-auth.ts +263 -0
- package/src/models/agent-card.ts +63 -0
- package/src/models/ink-audit.ts +205 -0
- package/src/models/ink-handshake.ts +123 -0
- package/src/models/intent.ts +201 -0
- package/src/models/key-entry.ts +52 -0
- package/src/models/profile.ts +31 -0
- package/test-vectors/README.md +129 -0
- package/test-vectors/encryption.json +90 -0
- package/test-vectors/handshake.json +482 -0
- package/test-vectors/jcs.json +30 -0
- package/test-vectors/key-rotation.json +101 -0
- package/test-vectors/keys.json +32 -0
- package/test-vectors/receipts-and-audit.json +142 -0
- package/test-vectors/replay.json +88 -0
- package/test-vectors/signing.json +61 -0
- package/test-vectors/witness.json +394 -0
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
# INK Introduction Receipts Extension v0.1
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
Draft
|
|
5
|
+
|
|
6
|
+
## Last Updated
|
|
7
|
+
23 March 2026
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
This specification defines a protocol-level extension for verifiable introductions in INK.
|
|
12
|
+
|
|
13
|
+
It introduces a signed introduction artifact that allows agents to prove that:
|
|
14
|
+
- an introduction workflow occurred
|
|
15
|
+
- a specific introducer participated
|
|
16
|
+
- the introduction reached a defined outcome
|
|
17
|
+
- the artifact is linked to the underlying INK exchange
|
|
18
|
+
|
|
19
|
+
This extension is intended to strengthen Tulpa's warm-path and introduction flows without requiring private relationship context to be published publicly.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 1. Problem
|
|
24
|
+
|
|
25
|
+
The core INK handshake and the message receipt extension provide strong evidence that messages were sent, received, and acted upon.
|
|
26
|
+
|
|
27
|
+
They do not yet provide a first-class artifact for the distinct social action of an introduction.
|
|
28
|
+
|
|
29
|
+
This creates several gaps:
|
|
30
|
+
|
|
31
|
+
1. A completed introduction is visible only as a series of lower-level intents, resolutions, and local UI actions.
|
|
32
|
+
2. There is no portable proof that a specific introducer approved or forwarded an introduction.
|
|
33
|
+
3. Trust-path explanations cannot rely on a standardized signed artifact.
|
|
34
|
+
4. Implementations cannot exchange or export introduction provenance in an interoperable way.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 2. Design Goals
|
|
39
|
+
|
|
40
|
+
This extension aims to provide:
|
|
41
|
+
- a signed, portable proof of introduction workflow outcomes
|
|
42
|
+
- linkage to the original INK exchange
|
|
43
|
+
- clear role semantics for requester, introducer, and introduced parties
|
|
44
|
+
- local-first storage with optional selective sharing
|
|
45
|
+
- compatibility with INK auditability and authorization chains
|
|
46
|
+
|
|
47
|
+
This extension does not aim to:
|
|
48
|
+
- publish private introduction context by default
|
|
49
|
+
- replace generic INK delivery/disposition receipts
|
|
50
|
+
- create a public reputation or ranking layer
|
|
51
|
+
- encode arbitrary social-graph claims without underlying workflow evidence
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 3. Core Model
|
|
56
|
+
|
|
57
|
+
An introduction receipt is a distinct INK message type.
|
|
58
|
+
|
|
59
|
+
It is not:
|
|
60
|
+
- an `intentType`
|
|
61
|
+
- a replacement for `network.tulpa.receipt`
|
|
62
|
+
- a public ATP record by default
|
|
63
|
+
|
|
64
|
+
It is a signed artifact that attests to the outcome of an introduction-related workflow.
|
|
65
|
+
|
|
66
|
+
### 3.1 Roles
|
|
67
|
+
|
|
68
|
+
This specification uses the following roles:
|
|
69
|
+
|
|
70
|
+
- **requester**: the agent that asked for an introduction
|
|
71
|
+
- **introducer**: the agent representing the person deciding whether to bridge the parties
|
|
72
|
+
- **beneficiary**: the party the requester wants to meet
|
|
73
|
+
- **target**: the counterparty being introduced to the beneficiary
|
|
74
|
+
|
|
75
|
+
For the common case:
|
|
76
|
+
- requester = beneficiary
|
|
77
|
+
- target = person the beneficiary wants to meet
|
|
78
|
+
|
|
79
|
+
The model keeps these fields separate so future workflows can support assistant-mediated or delegated requests without changing the wire shape.
|
|
80
|
+
|
|
81
|
+
### 3.2 Receipt Trigger
|
|
82
|
+
|
|
83
|
+
An introduction receipt SHOULD be issued when an introduction workflow reaches one of these terminal states:
|
|
84
|
+
- approved
|
|
85
|
+
- declined
|
|
86
|
+
- forwarded
|
|
87
|
+
- completed
|
|
88
|
+
- expired
|
|
89
|
+
|
|
90
|
+
An introduction receipt MUST NOT be emitted for every intermediate step.
|
|
91
|
+
It is an outcome artifact, not a transcript replacement.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 4. Wire Format
|
|
96
|
+
|
|
97
|
+
### 4.1 Message Type
|
|
98
|
+
|
|
99
|
+
This extension defines a new INK message type:
|
|
100
|
+
|
|
101
|
+
`network.tulpa.introduction_receipt`
|
|
102
|
+
|
|
103
|
+
### 4.2 Envelope
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"protocol": "ink/0.1",
|
|
108
|
+
"type": "network.tulpa.introduction_receipt",
|
|
109
|
+
"id": "01JQ....",
|
|
110
|
+
"correlationId": "01JQ....",
|
|
111
|
+
"from": "did:plc:introducer",
|
|
112
|
+
"to": "did:plc:requester",
|
|
113
|
+
"requesterDid": "did:plc:requester",
|
|
114
|
+
"introducerDid": "did:plc:introducer",
|
|
115
|
+
"beneficiaryDid": "did:plc:beneficiary",
|
|
116
|
+
"targetDid": "did:plc:target",
|
|
117
|
+
"status": "forwarded",
|
|
118
|
+
"purpose": "Warm introduction for hiring conversation",
|
|
119
|
+
"relatedIntentId": "01JQ....",
|
|
120
|
+
"relatedResolutionId": "01JQ....",
|
|
121
|
+
"contextHash": "a4c8...",
|
|
122
|
+
"nonce": "<base64url>",
|
|
123
|
+
"timestamp": "2026-03-23T12:00:00Z"
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 4.3 Required Fields
|
|
128
|
+
|
|
129
|
+
| Field | Description |
|
|
130
|
+
|------|-------------|
|
|
131
|
+
| `protocol` | MUST be `ink/0.1` |
|
|
132
|
+
| `type` | MUST be `network.tulpa.introduction_receipt` |
|
|
133
|
+
| `id` | Unique ULID or equivalent globally unique identifier |
|
|
134
|
+
| `correlationId` | Correlates the receipt to the introduction workflow |
|
|
135
|
+
| `from` | Sender of the receipt |
|
|
136
|
+
| `to` | Primary recipient of the receipt |
|
|
137
|
+
| `requesterDid` | DID of the requesting agent |
|
|
138
|
+
| `introducerDid` | DID of the introducing agent |
|
|
139
|
+
| `beneficiaryDid` | DID of the party seeking the introduction |
|
|
140
|
+
| `targetDid` | DID of the party being introduced |
|
|
141
|
+
| `status` | Outcome of the introduction workflow |
|
|
142
|
+
| `purpose` | Short human-meaningful statement of purpose |
|
|
143
|
+
| `nonce` | Replay protection nonce |
|
|
144
|
+
| `timestamp` | Receipt creation time |
|
|
145
|
+
|
|
146
|
+
### 4.4 Optional Fields
|
|
147
|
+
|
|
148
|
+
| Field | Description |
|
|
149
|
+
|------|-------------|
|
|
150
|
+
| `relatedIntentId` | Stage 1 intent or application-layer intro request that triggered the workflow |
|
|
151
|
+
| `relatedResolutionId` | Final resolution identifier if one exists |
|
|
152
|
+
| `note` | Optional short note from the introducer or implementation |
|
|
153
|
+
| `contextHash` | SHA-256 hex digest of a locally stored private context bundle |
|
|
154
|
+
| `authorizationChainRef` | Reference to an authorization chain artifact if used |
|
|
155
|
+
| `expiresAt` | Optional expiry for the receipt's asserted relevance, not its validity |
|
|
156
|
+
|
|
157
|
+
### 4.5 Status Values
|
|
158
|
+
|
|
159
|
+
The `status` field MUST be one of:
|
|
160
|
+
|
|
161
|
+
| Status | Meaning |
|
|
162
|
+
|--------|---------|
|
|
163
|
+
| `approved` | Introducer approved the introduction request but forwarding may not yet have happened |
|
|
164
|
+
| `declined` | Introducer declined to make the introduction |
|
|
165
|
+
| `forwarded` | Introducer forwarded the intro to the target or otherwise initiated the bridge |
|
|
166
|
+
| `completed` | The introduction was accepted and the bridge was established |
|
|
167
|
+
| `expired` | The intro workflow expired without completion |
|
|
168
|
+
|
|
169
|
+
Implementations SHOULD use:
|
|
170
|
+
- `approved` when the introducer has given consent but delivery to the target is not yet complete
|
|
171
|
+
- `forwarded` when the introducer has actually sent the bridge
|
|
172
|
+
- `completed` only when the introduction reached the intended counterparties successfully
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 5. Delivery and Recipients
|
|
177
|
+
|
|
178
|
+
### 5.1 Delivery Path
|
|
179
|
+
|
|
180
|
+
Introduction receipts SHOULD be delivered over HTTP using a dedicated endpoint:
|
|
181
|
+
|
|
182
|
+
`POST /ink/v1/introduction-receipt`
|
|
183
|
+
|
|
184
|
+
This keeps them distinct from generic delivery/disposition receipts.
|
|
185
|
+
|
|
186
|
+
### 5.2 Recipients
|
|
187
|
+
|
|
188
|
+
At minimum, the receipt MUST be sent to the requester.
|
|
189
|
+
|
|
190
|
+
The receipt MAY also be sent to:
|
|
191
|
+
- the beneficiary, if different from the requester
|
|
192
|
+
- the target, when the status is `forwarded` or `completed`
|
|
193
|
+
|
|
194
|
+
Implementations MUST NOT send the receipt to unrelated third parties.
|
|
195
|
+
|
|
196
|
+
### 5.3 Loop Prevention
|
|
197
|
+
|
|
198
|
+
Receiving a `network.tulpa.introduction_receipt` MUST NOT trigger:
|
|
199
|
+
- a generic message receipt
|
|
200
|
+
- another introduction receipt
|
|
201
|
+
|
|
202
|
+
This follows the same loop-prevention principle as generic INK receipts.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## 6. Signature and Replay Protection
|
|
207
|
+
|
|
208
|
+
Introduction receipts are full INK messages.
|
|
209
|
+
|
|
210
|
+
They MUST:
|
|
211
|
+
- be signed using the standard INK Ed25519 request signing flow
|
|
212
|
+
- include a nonce
|
|
213
|
+
- include a timestamp
|
|
214
|
+
- be replay-checked under the same nonce window as other INK messages
|
|
215
|
+
|
|
216
|
+
The signature base SHOULD follow the same pattern as other INK endpoints:
|
|
217
|
+
|
|
218
|
+
```text
|
|
219
|
+
ink/0.1
|
|
220
|
+
POST
|
|
221
|
+
/ink/v1/introduction-receipt
|
|
222
|
+
<recipientDid>
|
|
223
|
+
<JCS(body)>
|
|
224
|
+
<timestamp>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
If a receipt is sent to multiple recipients, each HTTP request MUST be signed for the specific recipient DID.
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## 7. Privacy Model
|
|
232
|
+
|
|
233
|
+
### 7.1 Local-First Storage
|
|
234
|
+
|
|
235
|
+
Introduction receipts MUST be treated as local application data by default.
|
|
236
|
+
|
|
237
|
+
They SHOULD be stored inside each relevant participant's local application state and SHOULD NOT be published to ATP by default.
|
|
238
|
+
|
|
239
|
+
### 7.2 Minimal Disclosure
|
|
240
|
+
|
|
241
|
+
The receipt SHOULD contain only the minimum information needed to prove that the introduction workflow occurred.
|
|
242
|
+
|
|
243
|
+
Sensitive framing, notes, or relationship context SHOULD remain local and MAY be referenced indirectly through `contextHash`.
|
|
244
|
+
|
|
245
|
+
### 7.3 Selective Sharing
|
|
246
|
+
|
|
247
|
+
Users MAY export or share introduction receipts selectively.
|
|
248
|
+
|
|
249
|
+
Any future ATP publication of introduction receipts MUST be:
|
|
250
|
+
- opt-in
|
|
251
|
+
- purpose-specific
|
|
252
|
+
- documented in a separate spec
|
|
253
|
+
|
|
254
|
+
### 7.4 Trust Distance and Graph Use
|
|
255
|
+
|
|
256
|
+
Introduction receipts MAY be used to explain warm paths or trust distance inside Tulpa.
|
|
257
|
+
|
|
258
|
+
They MUST NOT be used as a generic public popularity score or implicit endorsement outside the introduction workflow context.
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## 8. Relationship to Existing INK Artifacts
|
|
263
|
+
|
|
264
|
+
### 8.1 Generic Message Receipts
|
|
265
|
+
|
|
266
|
+
`network.tulpa.receipt` answers:
|
|
267
|
+
"What happened to this message?"
|
|
268
|
+
|
|
269
|
+
`network.tulpa.introduction_receipt` answers:
|
|
270
|
+
"What happened to this introduction workflow?"
|
|
271
|
+
|
|
272
|
+
Implementations MUST keep these concepts separate.
|
|
273
|
+
|
|
274
|
+
### 8.2 Resolutions
|
|
275
|
+
|
|
276
|
+
Introduction receipts complement, but do not replace, `network.tulpa.resolution`.
|
|
277
|
+
|
|
278
|
+
Resolutions capture the final handshake outcome.
|
|
279
|
+
Introduction receipts capture the social trust artifact of a completed or declined introduction path.
|
|
280
|
+
|
|
281
|
+
### 8.3 Audit Events
|
|
282
|
+
|
|
283
|
+
Introduction receipt issuance SHOULD be mirrored into the audit chain with event types such as:
|
|
284
|
+
- `introduction.requested`
|
|
285
|
+
- `introduction.approved`
|
|
286
|
+
- `introduction.declined`
|
|
287
|
+
- `introduction.forwarded`
|
|
288
|
+
- `introduction.completed`
|
|
289
|
+
- `introduction.receipt_sent`
|
|
290
|
+
- `introduction.receipt_received`
|
|
291
|
+
|
|
292
|
+
These event types SHOULD be added in `specs/ink-auditability.md` if this extension is adopted.
|
|
293
|
+
|
|
294
|
+
### 8.4 Authorization Chains
|
|
295
|
+
|
|
296
|
+
If the introduction depends on delegated authority or multi-hop approval, the receipt MAY reference an authorization chain artifact.
|
|
297
|
+
|
|
298
|
+
The receipt itself does not replace authorization chains.
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## 9. Access Control
|
|
303
|
+
|
|
304
|
+
An agent receiving an introduction receipt MUST verify that it is an intended participant in the workflow.
|
|
305
|
+
|
|
306
|
+
An implementation MUST reject the receipt with `access_denied` if:
|
|
307
|
+
- the recipient is not the requester
|
|
308
|
+
- the recipient is not the beneficiary when explicitly addressed
|
|
309
|
+
- the recipient is not the target when explicitly addressed
|
|
310
|
+
|
|
311
|
+
The implementation SHOULD also verify:
|
|
312
|
+
- that the signer matches `from`
|
|
313
|
+
- that `introducerDid` is consistent with the signer when the introducer is the sender
|
|
314
|
+
- that the receipt references a known or expected correlation when available
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## 10. Lexicon Shape
|
|
319
|
+
|
|
320
|
+
Recommended lexicon ID:
|
|
321
|
+
|
|
322
|
+
`network.tulpa.ink.introductionReceipt`
|
|
323
|
+
|
|
324
|
+
Recommended required properties:
|
|
325
|
+
|
|
326
|
+
```ts
|
|
327
|
+
type InkIntroductionReceipt = {
|
|
328
|
+
protocol: "ink/0.1"
|
|
329
|
+
type: "network.tulpa.introduction_receipt"
|
|
330
|
+
id: string
|
|
331
|
+
correlationId: string
|
|
332
|
+
from: string
|
|
333
|
+
to: string
|
|
334
|
+
requesterDid: string
|
|
335
|
+
introducerDid: string
|
|
336
|
+
beneficiaryDid: string
|
|
337
|
+
targetDid: string
|
|
338
|
+
status: "approved" | "declined" | "forwarded" | "completed" | "expired"
|
|
339
|
+
purpose: string
|
|
340
|
+
nonce: string
|
|
341
|
+
timestamp: string
|
|
342
|
+
relatedIntentId?: string
|
|
343
|
+
relatedResolutionId?: string
|
|
344
|
+
note?: string
|
|
345
|
+
contextHash?: string
|
|
346
|
+
authorizationChainRef?: string
|
|
347
|
+
expiresAt?: string
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## 11. Example Flows
|
|
354
|
+
|
|
355
|
+
### 11.1 Approved but Not Yet Forwarded
|
|
356
|
+
|
|
357
|
+
1. Requester sends intro-related intent
|
|
358
|
+
2. Introducer approves internally
|
|
359
|
+
3. Introducer emits `network.tulpa.introduction_receipt` with `status = approved`
|
|
360
|
+
4. Requester stores artifact and updates UI
|
|
361
|
+
|
|
362
|
+
### 11.2 Forwarded
|
|
363
|
+
|
|
364
|
+
1. Introducer sends the actual bridge message to target
|
|
365
|
+
2. Introducer emits introduction receipt with `status = forwarded`
|
|
366
|
+
3. Requester receives proof that the bridge was made
|
|
367
|
+
|
|
368
|
+
### 11.3 Completed
|
|
369
|
+
|
|
370
|
+
1. Target accepts or bridge is otherwise established
|
|
371
|
+
2. Introducer or receiving implementation emits introduction receipt with `status = completed`
|
|
372
|
+
3. Relevant parties store the final trust artifact
|
|
373
|
+
|
|
374
|
+
### 11.4 Declined
|
|
375
|
+
|
|
376
|
+
1. Introducer declines the request
|
|
377
|
+
2. Introducer emits receipt with `status = declined`
|
|
378
|
+
3. Requester receives a signed proof of decline and explanatory note if allowed
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## 12. Storage and Export
|
|
383
|
+
|
|
384
|
+
Implementations SHOULD store introduction receipts in a dedicated local collection or table.
|
|
385
|
+
|
|
386
|
+
Suggested fields:
|
|
387
|
+
- receipt id
|
|
388
|
+
- correlation id
|
|
389
|
+
- participant DIDs
|
|
390
|
+
- status
|
|
391
|
+
- signed payload
|
|
392
|
+
- message hash
|
|
393
|
+
- created at
|
|
394
|
+
- received at
|
|
395
|
+
|
|
396
|
+
Implementations MUST support exporting introduction receipts in a portable JSON format on user request.
|
|
397
|
+
|
|
398
|
+
The export SHOULD include:
|
|
399
|
+
- the signed receipt payload
|
|
400
|
+
- transport metadata sufficient for verification
|
|
401
|
+
- any related resolution or authorization references that the user is allowed to export
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## 13. UI / Product Requirements
|
|
406
|
+
|
|
407
|
+
Tulpa or other INK implementations adopting this extension SHOULD expose:
|
|
408
|
+
- a human-readable intro history
|
|
409
|
+
- clear explanation of who introduced whom
|
|
410
|
+
- the current intro status
|
|
411
|
+
- the reason or purpose statement
|
|
412
|
+
- the fact that the proof is signed and portable
|
|
413
|
+
|
|
414
|
+
The UI SHOULD avoid:
|
|
415
|
+
- gamified trust scores
|
|
416
|
+
- public leaderboards of introductions
|
|
417
|
+
- exposing hidden third-party context without consent
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## 14. Error Handling
|
|
422
|
+
|
|
423
|
+
Implementations SHOULD use standard INK structured errors where possible.
|
|
424
|
+
|
|
425
|
+
Recommended error codes:
|
|
426
|
+
- `invalid_receipt`
|
|
427
|
+
- `access_denied`
|
|
428
|
+
- `unknown_correlation`
|
|
429
|
+
- `signature_failed`
|
|
430
|
+
- `replay_detected`
|
|
431
|
+
- `unsupported_extension`
|
|
432
|
+
|
|
433
|
+
If the receiver does not support this extension, it SHOULD return `unsupported_extension`.
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## 15. Compatibility and Rollout
|
|
438
|
+
|
|
439
|
+
This extension is optional.
|
|
440
|
+
|
|
441
|
+
Agents SHOULD advertise support in Agent Card capabilities.
|
|
442
|
+
|
|
443
|
+
Recommended capability shape:
|
|
444
|
+
|
|
445
|
+
```json
|
|
446
|
+
{
|
|
447
|
+
"capabilities": {
|
|
448
|
+
"introductionReceipts": {
|
|
449
|
+
"send": true,
|
|
450
|
+
"receive": true,
|
|
451
|
+
"statuses": ["approved", "declined", "forwarded", "completed", "expired"]
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Senders MUST NOT assume support unless capability discovery or prior negotiation indicates it.
|
|
458
|
+
|
|
459
|
+
If the recipient does not support introduction receipts, the sender MAY:
|
|
460
|
+
- fall back to local-only receipt generation
|
|
461
|
+
- rely on generic message receipts and audit events only
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
## 16. Test Vectors and Compliance
|
|
466
|
+
|
|
467
|
+
If adopted, this extension SHOULD add:
|
|
468
|
+
- signed receipt test vectors
|
|
469
|
+
- replay-protection test vectors
|
|
470
|
+
- multi-recipient delivery examples
|
|
471
|
+
- correlation-link validation cases
|
|
472
|
+
|
|
473
|
+
Compliance checks SHOULD verify that an implementation:
|
|
474
|
+
- validates required fields
|
|
475
|
+
- verifies signatures
|
|
476
|
+
- enforces participant access control
|
|
477
|
+
- prevents receipt loops
|
|
478
|
+
- exports receipts portably
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
## 17. Recommended Follow-On Implementation Work
|
|
483
|
+
|
|
484
|
+
The Tulpa codebase SHOULD next implement:
|
|
485
|
+
|
|
486
|
+
1. a lexicon file for `network.tulpa.ink.introductionReceipt`
|
|
487
|
+
2. receipt verification and persistence utilities
|
|
488
|
+
3. a local store for introduction receipts
|
|
489
|
+
4. owner API endpoints for intro history and proof export
|
|
490
|
+
5. UI surfaces for warm-path trust explanation
|
|
491
|
+
6. audit event additions for introduction lifecycle states
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
## 18. Open Questions
|
|
496
|
+
|
|
497
|
+
1. Should `completed` be emitted only by the introducer, or may the beneficiary or target also finalize it?
|
|
498
|
+
2. Should `approved` be optional if `forwarded` follows immediately?
|
|
499
|
+
3. Should `contextHash` commit to a standardized canonical bundle shape?
|
|
500
|
+
4. Should there be a compact participant visibility field for cases where the target should not receive the full receipt?
|
|
501
|
+
5. Should future ATP publication support a redacted proof form derived from the local receipt?
|