Skip to content

Commit fceddce

Browse files
authored
Merge pull request #105 from ar-io/codex/feat/receipts-doc
docs(upload): add receipts guide flow and verification guidance, add glossary to dropdown nav and add winstons and winc to glossary
2 parents 021e341 + b475e74 commit fceddce

File tree

11 files changed

+289
-11
lines changed

11 files changed

+289
-11
lines changed

content/build/upload/index.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ Before uploading, learn best practices for structuring and tagging your data for
152152
description="Create folder structures and host websites"
153153
href="/build/upload/manifests"
154154
/>
155+
<Card
156+
title="Receipts"
157+
description="Capture timestamped upload attestations to preserve chronology and auditability"
158+
href="/build/upload/receipts"
159+
/>
155160
<Card
156161
title="Encryption"
157162
description="Secure your data with client-side encryption"

content/build/upload/manifests.mdx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,14 @@ This makes HTML more readable and ensures links remain valid even if the hosting
253253
## Next Steps
254254

255255
<Cards>
256+
<Card
257+
href="/build/upload/receipts"
258+
title="Receipts"
259+
icon={<Upload />}
260+
>
261+
Capture timestamped upload attestations for chronology and audits.
262+
</Card>
263+
256264
<Card
257265
href="/build/upload/encryption"
258266
title="Data Encryption"

content/build/upload/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"turbo-credits",
1010
"tagging",
1111
"manifests",
12+
"receipts",
1213
"encryption"
1314
]
1415
}

content/build/upload/receipts.mdx

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
---
2+
title: "Receipts"
3+
description: "Understand Turbo upload receipts for chronology, auditability, and later verification workflows"
4+
---
5+
6+
Turbo upload receipts provide a durable record of what was uploaded, who uploaded it, and what upload cost was assessed in Winston Credits (`winc`). They are useful for provenance, compliance, incident response, and operational debugging.
7+
8+
## What Are Turbo Receipts?
9+
10+
A Turbo receipt is a signed upload attestation returned by Turbo upload flows when a data item is successfully accepted and processed.
11+
12+
In practice, receipts help you:
13+
14+
- Link app-level records to immutable data item IDs
15+
- Track upload ownership and storage cost (`winc`)
16+
- Keep machine-readable proof metadata for investigations and audits
17+
18+
<Callout type="info">
19+
Receipts are proof of Turbo upload acceptance and signed receipt metadata for
20+
a specific upload event. They are not a full substitute for your own
21+
retrieval checks, gateway checks, or finality policies.
22+
</Callout>
23+
24+
## Why Time and Ordering Matter
25+
26+
Receipt timestamps are especially valuable because they let you prove when upload events occurred and how related uploads were ordered.
27+
28+
- A receipt `timestamp` supports evidence of event time in incident and audit workflows.
29+
- Ordered receipts create chronology across related data items (for example, original item, revision, and derived artifacts).
30+
- Chronology improves chain-of-custody reconstruction and post-incident analysis.
31+
32+
For production systems, preserving upload order can be as important as preserving data IDs.
33+
34+
## When Receipts Are Created
35+
36+
Turbo receipts are created in three common contexts:
37+
38+
1. Standard SDK uploads: `turbo.upload()` and `turbo.uploadFile()` return upload result payloads that include receipt metadata such as `id`, `owner`, `winc`, `dataCaches`, and `fastFinalityIndexes`.
39+
2. Multipart uploads: for larger uploads that use chunking, Turbo finalizes the upload and returns a finalized receipt payload when multipart status reaches `FINALIZED`.
40+
3. x402 uploads: Turbo still returns an upload receipt, and x402 tooling can also provide a separate payment settlement receipt.
41+
42+
Regardless of flow, store receipt timestamps and your own sequence metadata so ordered events can be reconstructed later.
43+
44+
<Callout type="warning">
45+
Turbo does not store and retrieve your receipts for you. If you need receipts
46+
later, persist the exact payload returned by Turbo in your own storage. You
47+
can also optionally store receipt records on Arweave for long-term archival.
48+
See [Capturing Receipts in Turbo
49+
SDK](#capturing-receipts-in-turbo-sdk) for an implementation example.
50+
</Callout>
51+
52+
## Receipt Anatomy
53+
54+
| Field | Meaning | Notes |
55+
| ----- | ------- | ----- |
56+
| `id` | Data item transaction ID | Primary key to join with your app records |
57+
| `owner` | Normalized address that signed/owns the data item | Useful for audit and policy checks |
58+
| `winc` | Upload cost measured in Winston Credits | Useful for billing and reporting. See [Paying for Uploads](/build/upload/turbo-credits) for unit and payment context |
59+
| `dataCaches` | Caches that accepted the data item | Operational visibility for upload path |
60+
| `fastFinalityIndexes` | Fast finality indexes that accepted the data item | Useful for observability |
61+
| `timestamp` | Receipt creation time in milliseconds | Core field for chronology, ordering, and evidence of event time |
62+
| `version` | Receipt schema/version identifier | Determines how verification inputs should be interpreted |
63+
| `deadlineHeight` | Deadline block height recorded in receipt payload | Useful as additional upload context |
64+
| `public` | Public key that signed the receipt | Needed to verify signature validity |
65+
| `signature` | Base64URL receipt signature | Required to verify receipt authenticity |
66+
67+
Some fields vary by upload path and service response shape. Do not assume every SDK return object includes every signed receipt field in all flows.
68+
69+
## Capturing Receipts in Turbo SDK
70+
71+
Capture the upload response as your receipt record and persist it alongside your own object IDs. Below is a simple example, in practice you might chose to store this alongside your existing logs in S3, Sentry or similar:
72+
73+
```typescript
74+
import fs from "fs";
75+
import { TurboFactory } from "@ardrive/turbo-sdk";
76+
77+
const turbo = TurboFactory.authenticated({ privateKey });
78+
79+
const receipt = await turbo.uploadFile({
80+
fileStreamFactory: () => fs.createReadStream("./report.json"),
81+
fileSizeFactory: () => fs.statSync("./report.json").size,
82+
dataItemOpts: {
83+
tags: [
84+
{ name: "Content-Type", value: "application/json" },
85+
{ name: "App-Name", value: "AnalyticsPipeline-v1.0" },
86+
],
87+
},
88+
});
89+
90+
await fetch("https://api.yourdomain.com/upload-receipts", {
91+
method: "POST",
92+
headers: { "Content-Type": "application/json" },
93+
body: JSON.stringify({
94+
appObjectId: "report-2026-02-16",
95+
capturedAt: new Date().toISOString(),
96+
receipt,
97+
}),
98+
});
99+
100+
console.log("Stored Turbo receipt:", {
101+
id: receipt.id,
102+
timestamp: receipt.timestamp,
103+
owner: receipt.owner,
104+
winc: receipt.winc,
105+
});
106+
```
107+
108+
<Callout type="info">
109+
Turbo CLI upload commands print JSON output that can be captured as a receipt
110+
record in scripts and CI pipelines.
111+
</Callout>
112+
113+
## Why Receipts Matter Across ar.io Use Cases
114+
115+
| AR.IO Use Case | Receipt Value |
116+
| -------------- | ------------- |
117+
| [File Storage](https://ar.io/use-cases/file-storage/) | Map internal file objects to immutable upload IDs and timestamped upload events |
118+
| [Websites & Apps](https://ar.io/use-cases/websites-and-apps/) | Track deployment artifacts and ordering of publish history over time |
119+
| [Apps & Game Assets](https://ar.io/use-cases/apps-and-game-assets/) | Prove that specific asset versions were accepted and in which sequence they were released |
120+
| [Media Provenance](https://ar.io/use-cases/media-provenance/) | Establish chain-of-custody metadata for original and derivative media with event ordering |
121+
| [Verifiable AI Data](https://ar.io/use-cases/verifiable-ai-data/) | Attach signed upload evidence and chronology to datasets, prompts, and model outputs |
122+
| [Verifiable Computing](https://ar.io/use-cases/verifiable-computing/) | Bind compute inputs/outputs to durable upload receipts for reproducibility and timeline checks |
123+
| [Durable Financial Data](https://ar.io/use-cases/durable-financial-data/) | Maintain publish-time evidence for disclosures, reports, and compliance records |
124+
125+
## Deep Dive: Media Provenance
126+
127+
Receipts strengthen provenance workflows by giving each media upload a signed event record with a timestamp and ordering context.
128+
129+
- Preserve the receipt for original media ingestion
130+
- Store receipts for edited or transformed derivatives
131+
- Link parent and derivative records in your metadata model
132+
- Use receipt IDs, timestamps, and signed fields as part of publishing audit trails
133+
134+
This gives teams a clearer chain-of-custody model for authenticity claims, moderation workflows, and external verification requests.
135+
136+
## Deep Dive: Verifiable AI Data
137+
138+
AI pipelines benefit from receipts because reproducibility depends on stable, attributable inputs and outputs over time.
139+
140+
- Store receipts for datasets, prompts, and generated artifacts
141+
- Link receipts to model versions, run IDs, and evaluation jobs
142+
- Preserve ordered receipt timelines to reconstruct dataset-to-output lineage
143+
- Use receipts as evidence in regulated or policy-bound AI workflows
144+
145+
This makes lineage more transparent and reduces ambiguity when debugging model behavior or validating published results.
146+
147+
## Verifying Receipts Later
148+
149+
Delayed verification is valuable for audits, disputes, compliance reviews, and reproducibility checks that happen long after initial upload.
150+
151+
### Verification Checklist
152+
153+
1. Load the stored receipt payload.
154+
2. Validate required fields (`id`, `version`, `public`, `signature`, and contextual fields you depend on).
155+
3. Verify the signature against the public key using receipt-version-specific hashing/signing rules.
156+
4. Confirm data item status and availability via Turbo or gateway status endpoints.
157+
5. Compare verified receipt data with your internal upload metadata and flag mismatches.
158+
159+
Example verification workflow:
160+
161+
```typescript
162+
type StoredReceipt = {
163+
id: string;
164+
version?: string;
165+
public?: string;
166+
signature?: string;
167+
timestamp?: number;
168+
owner?: string;
169+
};
170+
171+
async function verifyStoredReceipt(receipt: StoredReceipt) {
172+
if (!receipt.id || !receipt.version || !receipt.public || !receipt.signature) {
173+
throw new Error("Receipt is missing required verification fields.");
174+
}
175+
176+
// Implement this in your backend with version-aware receipt rules.
177+
const signatureValid = await verifyReceiptSignatureForVersion(receipt);
178+
if (!signatureValid) {
179+
throw new Error(`Invalid receipt signature for ${receipt.id}`);
180+
}
181+
182+
const statusResponse = await fetch(
183+
`https://upload.ardrive.io/v1/tx/${receipt.id}/status`,
184+
);
185+
186+
if (!statusResponse.ok) {
187+
throw new Error(`Unable to retrieve status for ${receipt.id}`);
188+
}
189+
190+
const status = await statusResponse.json();
191+
192+
return {
193+
id: receipt.id,
194+
signatureValid,
195+
status,
196+
};
197+
}
198+
```
199+
200+
<Callout type="warning">
201+
Verification inputs are receipt-version dependent. Do not assume every
202+
response field is signature-bound in every version, and do not assume a
203+
high-level SDK helper exists unless it is explicitly documented for your
204+
target version.
205+
</Callout>
206+
207+
## Best Practices
208+
209+
- Persist raw receipt payloads server-side and keep them immutable
210+
- Store receipts with your own object IDs, pipeline IDs, and environment metadata
211+
- Index by data item `id` for fast traceability across systems
212+
- Preserve upload chronology (for example sequence numbers, parent/child links, and timestamps)
213+
- Capture both upload receipts and payment receipts when using x402
214+
- Re-check status/finality in stricter workflows using service or gateway checks
215+
216+
<Callout type="warning">
217+
Treat a receipt as proof of Turbo upload acceptance and signing for that
218+
event, not as a blanket guarantee for every downstream retrieval state.
219+
</Callout>
220+
221+
## Next Steps
222+
223+
<Cards>
224+
<Card href="/build/upload/manifests" title="Manifests" icon={<FolderOpen />}>
225+
Connect receipt evidence to structured path-based content organization.
226+
</Card>
227+
228+
<Card href="/build/upload/encryption" title="Data Encryption" icon={<Shield />}>
229+
Protect sensitive content before uploading to permanent storage.
230+
</Card>
231+
232+
<Card
233+
href="/build/upload/x402-uploading-to-turbo"
234+
title="x402 Uploading To Turbo"
235+
icon={<CreditCard />}
236+
>
237+
Add just-in-time payment flows to your upload pipeline.
238+
</Card>
239+
240+
<Card
241+
href="/build/upload/turbo-credits"
242+
title="Paying for Uploads"
243+
icon={<CreditCard />}
244+
>
245+
Understand Turbo Credits, top ups, and funding workflows.
246+
</Card>
247+
</Cards>

content/build/upload/x402-uploading-to-turbo.mdx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ await turbo.uploadRawX402Data({
7070
});
7171
```
7272

73+
<Callout type="info">
74+
**Receipt context:** x402 integrations can surface both an upload receipt and a
75+
payment settlement receipt. For how to capture and store Turbo upload
76+
receipts, see [Receipts](/build/upload/receipts#verifying-receipts-later).
77+
</Callout>
78+
7379
### x402 Ecosystem Tooling
7480

7581
Using the raw data API, developers can upload data to Turbo with minimal code using existing x402 ecosystem tooling.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ description: "Key terms and definitions for the ar.io ecosystem"
77

88
AO (Actor Oriented) is a hyper-parallel computing platform built on Arweave that enables decentralized applications to run with unlimited computational capacity. AO provides the compute layer for ar.io's smart contracts and token operations.
99

10+
## Winston
11+
12+
Winston is the smallest unit of Arweave's native AR token. One AR equals 10^12 Winston.
13+
14+
## Winston Credits (winc)
15+
16+
Winston Credits (`winc`) are the unit used by Turbo to represent upload purchasing power. In Turbo contexts, receipt and balance fields often return values in `winc`.
17+
1018
## Public Key
1119

1220
A cryptographic key that can be shared publicly and is used to verify digital signatures or encrypt data. In the ar.io context, public keys are used to identify wallet addresses and verify transactions.

content/glossary/meta.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"title": "Glossary",
3+
"icon": "BookText",
4+
"root": true,
5+
"defaultOpen": false,
6+
"pages": ["index"]
7+
}

content/meta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"title": "ar.io Docs",
33
"root": true,
4-
"pages": ["...", "learn", "build", "sdks", "apis", "guides", "!migrated"]
4+
"pages": ["...", "learn", "build", "sdks", "apis", "glossary", "guides", "!migrated"]
55
}

redirects.mjs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -404,11 +404,6 @@ const redirects = [
404404
},
405405

406406
// Community and other pages
407-
{
408-
source: '/glossary',
409-
destination: '/glossary',
410-
permanent: true,
411-
},
412407
{
413408
source: '/community-resources',
414409
destination: '/',

src/components/page-actions.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,9 @@ export function ViewOptions({
8282
githubUrl: string;
8383
}) {
8484
const items = useMemo(() => {
85-
const fullMarkdownUrl =
86-
typeof window !== 'undefined'
87-
? new URL(markdownUrl, window.location.origin)
88-
: 'loading';
85+
// markdownUrl is already passed as an absolute URL, so avoid client-only
86+
// window access during render to keep server/client output deterministic.
87+
const fullMarkdownUrl = markdownUrl;
8988
const q = `Read ${fullMarkdownUrl}, I want to ask questions about it.`;
9089

9190
return [

0 commit comments

Comments
 (0)