Skip to content

feat: classify DIPs proposal rejections by area and nature#1041

Draft
MoonBoi9001 wants to merge 1 commit into
main-dips-rebasedfrom
mb9/add-dips-grpc-reject-reasons
Draft

feat: classify DIPs proposal rejections by area and nature#1041
MoonBoi9001 wants to merge 1 commit into
main-dips-rebasedfrom
mb9/add-dips-grpc-reject-reasons

Conversation

@MoonBoi9001
Copy link
Copy Markdown
Member

@MoonBoi9001 MoonBoi9001 commented Jun 5, 2026

TL;DR

Describes why the indexer rejects a DIPs proposal along two axes — which part of the agreement, and what kind of problem — plus an optional detail message, instead of one flat reason. This is the base of the DIPs validation work; the only change here is the shape of the reject response.

Motivation

When the indexer receives a DIPs agreement proposal over gRPC it answers accept or reject, and on a reject it returns a coded reason. With a single flat list of reasons, the sender (the Dipper service) has to recognise each specific value to know what to do, and a value it doesn't recognise tells it nothing — in particular, nothing about whether the proposal is permanently bad or could succeed if it were sent again later.

This describes a rejection along two axes instead: an area (timing, price, metadata, parties, auth, escrow, subgraph) and a nature, grouped into "invalid" — the request itself is bad — versus "declined" — well-formed, but the indexer won't or can't serve it, including a transient "busy". A reader that doesn't recognise a newer value on one axis can still act on the part it understands, and the nature directly signals whether sending it again could help, which is what the Dipper's back-off needs. This follows Rembrandt's review of the original flat-list version.

Summary

  • Replace the single reject reason with two axes plus an optional free-text detail string.
  • The nature has two families: Invalid (the request is bad) and Declined (won't or can't serve it).
  • Map every current error to an (area, nature); the mapping is exhaustive by design.
  • Regenerate the committed gRPC bindings from the updated protocol file.
  • Base of the DIPs indexer-validation stack; the feature PRs set these axes for their own checks.

Copy link
Copy Markdown
Contributor

@RembrandtK RembrandtK left a comment

Choose a reason for hiding this comment

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

I have reviewed at leaf level, a good set of options considered.

I wonder about the model of seeking to predict, how to group handling, and how to extend or provide more detail.

Might want to consider a model that splits and groups more by area than at leaf level of individual aspects. Having a MECE set of areas could help, for example the reason could be related to:

  • Agreement Timing
  • Agreement Conditions
  • Agreement Price
  • Agreement Metadata
  • Agreement Parties
  • Agreement Auth
  • Escrow
  • Subgraph

Might be able to orthogonally group into a set of what can be wrong, under two broad (extendable) categories:

  • Invalid
    • Failed to retrieve or not available
    • Unable to parse
    • Incorrect parameters
    • Expired or no longer valid
  • Declined
    • Not accepted (terms/price not accepted, party not accepted, etc)
    • Not supported (do not have capability or do not want to perform this type of work)
    • Too large/big (permanent capacity rejection)
    • Busy (could be be resubmitted later)

Additionally allowing optional extra text detail could help.

It might be not all combinations are applicable, but many would be. An extendable design would allow options to be added without breaking backwards compatibility, so that older software on either side could continue to work with still correct but less granular information.

Comment thread crates/dips/proto/indexer.proto Outdated
REJECT_REASON_PRICE_TOO_LOW = 1; /// The offered price is below the indexer's minimum.
REJECT_REASON_OTHER = 2; /// Any other reason (bad signature, etc.).
REJECT_REASON_OTHER = 2; /// Any other reason not covered by a more specific variant.
REJECT_REASON_SIGNER_NOT_AUTHORISED = 3; /// The proposal signer is not authorised on the escrow contract.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should authorised on the Recurring Agreement Manager, not the escrow contract?

Comment thread crates/dips/proto/indexer.proto Outdated
REJECT_REASON_UNSUPPORTED_NETWORK = 5; /// The subgraph's network is not supported by this indexer.
REJECT_REASON_SUBGRAPH_MANIFEST_UNAVAILABLE = 6; /// The subgraph manifest could not be fetched from IPFS.
REJECT_REASON_UNEXPECTED_SERVICE_PROVIDER = 7; /// The RCA service provider does not match this indexer.
REJECT_REASON_AGREEMENT_EXPIRED = 8; /// The agreement end time has already passed.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not needed as will as REJECT_REASON_DEADLINE_EXPIRED? Might have been picked up to correlate to endsAt rather than deadline', but do not need a reason for endsAt, should never be more restrictive than deadline'.

It might however be worth adding a reason for invalid agreement proposals (that is proposals with invalid values).

Comment thread crates/dips/proto/indexer.proto Outdated
REJECT_REASON_AGREEMENT_EXPIRED = 8; /// The agreement end time has already passed.
REJECT_REASON_UNSUPPORTED_METADATA_VERSION = 9; /// The metadata version is not supported.
REJECT_REASON_INVALID_SIGNATURE = 10; /// The proposal's signature failed to verify.
REJECT_REASON_SENDER_NOT_TRUSTED = 11; /// The proposal sender is not a trusted agreement manager.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How does this differ from REJECT_REASON_SIGNER_NOT_AUTHORISED?

Comment thread crates/dips/proto/indexer.proto Outdated
REJECT_REASON_SENDER_NOT_TRUSTED = 11; /// The proposal sender is not a trusted agreement manager.
REJECT_REASON_CAPACITY_EXCEEDED = 12; /// The indexer has reached its DIPs agreement capacity.
REJECT_REASON_MANIFEST_TOO_LARGE = 13; /// The subgraph manifest exceeds the maximum allowed size.
REJECT_REASON_REPLAY_DETECTED = 14; /// The proposal repeats an already-seen message.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should think if idepotency is better and practical, and/or if resending is valid anyway (if a previous rejection was for capacity for example).

For the first Dipper could fail to get a response, try to resend, and get a failure response. In the meantime the indexer could have accepted?

Comment thread crates/dips/proto/indexer.proto Outdated
@@ -46,12 +46,18 @@ enum ProposalResponse {
enum RejectReason {
REJECT_REASON_UNSPECIFIED = 0; /// Default / not set (used for ACCEPT responses).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this actually 'ACCEPTED' then, rather than an unspecified rejection? Or just do not define an enum member for 0? Could also logically overlap with REJECT_REASON_OTHER.

Comment thread crates/dips/proto/indexer.proto Outdated
REJECT_REASON_UNSPECIFIED = 0; /// Default / not set (used for ACCEPT responses).
REJECT_REASON_PRICE_TOO_LOW = 1; /// The offered price is below the indexer's minimum.
REJECT_REASON_OTHER = 2; /// Any other reason (bad signature, etc.).
REJECT_REASON_OTHER = 2; /// Any other reason not covered by a more specific variant.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Might be worth allowing an optional text field for extra information (regardless of which reason)?

The indexer answers a DIPs proposal over gRPC, but every rejection collapsed into one generic reason,
so the sender couldn't tell what was wrong or whether retrying might help. Describe a rejection by two
axes -- which part of the agreement and the kind of problem -- plus optional detail, degrading gracefully.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MoonBoi9001 MoonBoi9001 force-pushed the mb9/add-dips-grpc-reject-reasons branch from 0b4c34e to ca26d2b Compare June 5, 2026 14:00
@MoonBoi9001 MoonBoi9001 changed the title feat: bundle new gRPC reject reasons for DIPs validation feat: classify DIPs proposal rejections by area and nature Jun 5, 2026
@MoonBoi9001 MoonBoi9001 marked this pull request as draft June 5, 2026 14:09
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