Skip to content

refactor: /ucan/conclude allows multiple receipts in a single invocation - #7

Merged
alanshaw merged 1 commit into
mainfrom
ash/refactor/multi-conclude
Oct 13, 2026
Merged

alanshaw merged 1 commit into
mainfrom
ash/refactor/multi-conclude

Conversation

@alanshaw

Copy link
Copy Markdown
Member

Conclude arguments receipt: Link becomes receipts: [Link].

Comment thread blob.md
The receipt is a signal to the upload service to proceed with [accept blob]. A service implementation that does not require a signal from the client MAY issue the receipt itself when content is uploaded.

ℹ️ The client MUST use the [UCAN conclusion] capability to deliver the receipt to the awaiting service.
ℹ️ The client MUST use the [UCAN conclusion] capability to deliver the receipt to the awaiting service. A client that uploaded several blobs MAY deliver all of their receipts in one conclusion, and SHOULD read each blob's [accept blob receipt] from the conclusion's response container rather than polling for it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A client that uploaded several blobs MAY deliver all of their receipts in one conclusion

Should we mention the limit on how many receipts can be fitted into a single UCAN invocation? I feel "deliver all (...) in one conclusion" is not telling the whole story.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the implementation should be able to decide although we could specify a minimum an implementation is expected to support. For us, it's bounded by the number of items cbor-gen will allow in an array ~8,000 when encoding/decoding.

Comment thread ucan.md
The `args.receipts` field MUST be set to the links of the delivered [receipt] invocations. Note these are the links of the signed receipt invocations, not [task][UCAN task] links.

The receipt itself MUST be transmitted in the request [container][UCAN container] alongside the `/ucan/conclude` invocation. Invocation MUST fail with error name `ConclusionReceiptNotFound` if the linked receipt is not present in the request container.
One invocation delivers any number of receipts, and the field is always a list. Delivering many at once exists because a delivering agent often holds a receipt per blob of a large upload, and a round trip per receipt costs more than the work each one triggers. An empty list delivers nothing and MUST succeed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we mention the limit on how many receipts can be fitted into a single UCAN container?

Comment thread ucan.md
```go
type ConcludeArguments struct {
Receipt cid.Cid `cborgen:"receipt"`
Receipts []cid.Cid `cborgen:"receipts"`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, fil-one/RFC#29 is proposing a backwards-compatible approach:

The arguments gain an optional plural field — exactly one of receipt or receipts MUST be present

Personally, I prefer making a breaking change here to simplify future maintenance, as proposed here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, I specifically didn't do that since there's no user facing clients out there right now that we'd need to continue to support.

@alanshaw
alanshaw merged commit d91d99c into main Oct 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants