github.com/storacha/go-ucanto@v0.7.2/validator/error.go (about)

     1  package validator
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"math"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/ipld/go-ipld-prime/datamodel"
    12  	"github.com/storacha/go-ucanto/core/delegation"
    13  	"github.com/storacha/go-ucanto/core/ipld"
    14  	"github.com/storacha/go-ucanto/core/result/failure"
    15  	"github.com/storacha/go-ucanto/did"
    16  	"github.com/storacha/go-ucanto/ucan"
    17  	vdm "github.com/storacha/go-ucanto/validator/datamodel"
    18  )
    19  
    20  // go hack for union type -- unexported method cannot be implemented outside module limiting satisfying types
    21  type DelegationSubError interface {
    22  	failure.Failure
    23  	isDelegationSubError()
    24  }
    25  
    26  type InvalidProof interface {
    27  	failure.Failure
    28  	isInvalidProof()
    29  }
    30  
    31  type EscalatedCapabilityError[Caveats any] struct {
    32  	failure.NamedWithStackTrace
    33  	claimed   ucan.Capability[Caveats]
    34  	delegated ucan.Capability[Caveats]
    35  	cause     error
    36  }
    37  
    38  func NewEscalatedCapabilityError[Caveats any](claimed ucan.Capability[Caveats], delegated ucan.Capability[Caveats], cause error) EscalatedCapabilityError[Caveats] {
    39  	return EscalatedCapabilityError[Caveats]{failure.NamedWithCurrentStackTrace("EscalatedCapability"), claimed, delegated, cause}
    40  }
    41  
    42  func (ece EscalatedCapabilityError[Caveats]) Unwrap() error {
    43  	return ece.cause
    44  }
    45  
    46  func (ece EscalatedCapabilityError[Caveats]) Error() string {
    47  	return fmt.Sprintf("Constraint violation: %s", ece.cause.Error())
    48  }
    49  
    50  func (ece EscalatedCapabilityError[Caveats]) isDelegationSubError() {}
    51  
    52  type DelegationError interface {
    53  	failure.Failure
    54  	Causes() []DelegationSubError
    55  	Context() any
    56  	isDelegationError()
    57  }
    58  
    59  type delegationError struct {
    60  	failure.NamedWithStackTrace
    61  	causes  []DelegationSubError
    62  	context interface{}
    63  }
    64  
    65  func NewDelegationError(causes []DelegationSubError, context interface{}) DelegationError {
    66  	return delegationError{failure.NamedWithCurrentStackTrace("InvalidClaim"), causes, context}
    67  }
    68  
    69  func (de delegationError) Error() string {
    70  	return fmt.Sprintf("Cannot derive %s from delegated capabilities:\n%s", de.context, li(errors.Join(de.Unwrap()...).Error()))
    71  }
    72  
    73  func (de delegationError) Causes() []DelegationSubError {
    74  	return de.causes
    75  }
    76  
    77  func (de delegationError) Context() any {
    78  	return de.context
    79  }
    80  
    81  func (de delegationError) Unwrap() []error {
    82  	errs := make([]error, 0, len(de.causes))
    83  	for _, cause := range de.causes {
    84  		errs = append(errs, cause)
    85  	}
    86  	return errs
    87  }
    88  
    89  func (de delegationError) isDelegationError()    {}
    90  func (de delegationError) isDelegationSubError() {}
    91  
    92  type SessionEscalationError struct {
    93  	failure.NamedWithStackTrace
    94  	delegation delegation.Delegation
    95  	cause      error
    96  }
    97  
    98  func NewSessionEscalationError(delegation delegation.Delegation, cause error) InvalidProof {
    99  	return SessionEscalationError{failure.NamedWithCurrentStackTrace("SessionEscalation"), delegation, cause}
   100  }
   101  
   102  func (see SessionEscalationError) Error() string {
   103  	issuer := see.delegation.Issuer().DID()
   104  	return strings.Join([]string{
   105  		fmt.Sprintf("Delegation %s issued by %s has an invalid session", see.delegation.Link(), issuer),
   106  		li(see.cause.Error()),
   107  	}, "\n")
   108  }
   109  
   110  func (see SessionEscalationError) isInvalidProof() {}
   111  
   112  // BadSignature is a signature that could not be verified or has been verified
   113  // invalid. i.e. it is an [UnverifiableSignature] or an [InvalidSignature].
   114  type BadSignature interface {
   115  	InvalidProof
   116  	Issuer() ucan.Principal
   117  	Audience() ucan.Principal
   118  	Delegation() delegation.Delegation
   119  	isBadSignature()
   120  }
   121  
   122  // UnverifiableSignature is a signature that cannot be verified. i.e. some error
   123  // occurred when attempting to verify the signature.
   124  type UnverifiableSignature interface {
   125  	BadSignature
   126  	Unwrap() error
   127  	isUnverifiableSignature()
   128  }
   129  
   130  type UnverifiableSignatureError struct {
   131  	failure.NamedWithStackTrace
   132  	delegation delegation.Delegation
   133  	cause      error
   134  }
   135  
   136  func NewUnverifiableSignatureError(delegation delegation.Delegation, cause error) UnverifiableSignature {
   137  	return UnverifiableSignatureError{failure.NamedWithCurrentStackTrace("UnverifiableSignature"), delegation, cause}
   138  }
   139  
   140  func (use UnverifiableSignatureError) Issuer() ucan.Principal {
   141  	return use.delegation.Issuer()
   142  }
   143  
   144  func (use UnverifiableSignatureError) Audience() ucan.Principal {
   145  	return use.delegation.Audience()
   146  }
   147  
   148  func (use UnverifiableSignatureError) Delegation() delegation.Delegation {
   149  	return use.delegation
   150  }
   151  
   152  func (use UnverifiableSignatureError) Error() string {
   153  	issuer := use.Issuer().DID()
   154  	return fmt.Sprintf("Proof %s issued by %s cannot be verified:\n%s", use.delegation.Link(), issuer, li(use.cause.Error()))
   155  }
   156  
   157  func (use UnverifiableSignatureError) Unwrap() error {
   158  	return use.cause
   159  }
   160  
   161  func (use UnverifiableSignatureError) isUnverifiableSignature() {}
   162  func (use UnverifiableSignatureError) isBadSignature()          {}
   163  func (use UnverifiableSignatureError) isInvalidProof()          {}
   164  
   165  // InvalidSignature is a signature that is verified to be invalid.
   166  type InvalidSignature interface {
   167  	BadSignature
   168  	isInvalidSignature()
   169  }
   170  
   171  type InvalidSignatureError struct {
   172  	failure.NamedWithStackTrace
   173  	delegation delegation.Delegation
   174  	verifier   ucan.Verifier
   175  }
   176  
   177  func NewInvalidSignatureError(delegation delegation.Delegation, verifier ucan.Verifier) InvalidSignature {
   178  	return InvalidSignatureError{failure.NamedWithCurrentStackTrace("InvalidSignature"), delegation, verifier}
   179  }
   180  
   181  func (ise InvalidSignatureError) Issuer() ucan.Principal {
   182  	return ise.delegation.Issuer()
   183  }
   184  
   185  func (ise InvalidSignatureError) Audience() ucan.Principal {
   186  	return ise.delegation.Audience()
   187  }
   188  
   189  func (ise InvalidSignatureError) Delegation() delegation.Delegation {
   190  	return ise.delegation
   191  }
   192  
   193  func (ise InvalidSignatureError) Error() string {
   194  	issuer := ise.Issuer().DID()
   195  	key := ise.verifier.DID()
   196  	if strings.HasPrefix(issuer.String(), "did:key") {
   197  		return fmt.Sprintf(`Proof %s does not have a valid signature from %s`, ise.delegation.Link(), key)
   198  	}
   199  	return strings.Join([]string{
   200  		fmt.Sprintf("Proof %s issued by %s does not have a valid signature from %s", ise.delegation.Link(), issuer, key),
   201  		"  ℹ️ Issuer probably signed with a different key, which got rotated, invalidating delegations that were issued with prior keys",
   202  	}, "\n")
   203  }
   204  
   205  func (ise InvalidSignatureError) isInvalidSignature() {}
   206  func (ise InvalidSignatureError) isBadSignature()     {}
   207  func (ise InvalidSignatureError) isInvalidProof()     {}
   208  
   209  type UnavailableProof interface {
   210  	InvalidProof
   211  	Link() ucan.Link
   212  	isUnavailableProof()
   213  }
   214  
   215  type UnavailableProofError struct {
   216  	failure.NamedWithStackTrace
   217  	link  ucan.Link
   218  	cause error
   219  }
   220  
   221  func NewUnavailableProofError(link ucan.Link, cause error) UnavailableProof {
   222  	return UnavailableProofError{failure.NamedWithCurrentStackTrace("UnavailableProof"), link, cause}
   223  }
   224  
   225  func (upe UnavailableProofError) Unwrap() error {
   226  	return upe.cause
   227  }
   228  
   229  func (upe UnavailableProofError) Link() ucan.Link {
   230  	return upe.link
   231  }
   232  
   233  func (upe UnavailableProofError) Error() string {
   234  	messages := []string{
   235  		fmt.Sprintf(`Linked proof "%s" is not included and could not be resolved`, upe.link),
   236  	}
   237  	if upe.cause != nil {
   238  		messages = append(messages, li(fmt.Sprintf("Proof resolution failed with: %s", upe.cause.Error())))
   239  	}
   240  	return strings.Join(messages, "\n")
   241  }
   242  
   243  func (upe UnavailableProofError) isUnavailableProof() {}
   244  func (upe UnavailableProofError) isInvalidProof()     {}
   245  
   246  type UnresolvedDID interface {
   247  	InvalidProof
   248  	DID() did.DID
   249  	isUnresolvedDID()
   250  }
   251  
   252  type DIDKeyResolutionError struct {
   253  	failure.NamedWithStackTrace
   254  	did   did.DID
   255  	cause error
   256  }
   257  
   258  func NewDIDKeyResolutionError(did did.DID, cause error) UnresolvedDID {
   259  	return DIDKeyResolutionError{failure.NamedWithCurrentStackTrace("DIDKeyResolutionError"), did, cause}
   260  }
   261  
   262  func (dkre DIDKeyResolutionError) Unwrap() error {
   263  	return dkre.cause
   264  }
   265  
   266  func (dkre DIDKeyResolutionError) DID() did.DID {
   267  	return dkre.did
   268  }
   269  
   270  func (dkre DIDKeyResolutionError) Error() string {
   271  	return fmt.Sprintf("Unable to resolve '%s' key", dkre.did)
   272  }
   273  
   274  func (dkre DIDKeyResolutionError) isUnresolvedDID() {}
   275  func (dkre DIDKeyResolutionError) isInvalidProof()  {}
   276  
   277  type PrincipalAlignmentError struct {
   278  	failure.NamedWithStackTrace
   279  	audience   ucan.Principal
   280  	delegation delegation.Delegation
   281  }
   282  
   283  func NewPrincipalAlignmentError(audience ucan.Principal, delegation delegation.Delegation) failure.Failure {
   284  	return PrincipalAlignmentError{failure.NamedWithCurrentStackTrace("InvalidAudience"), audience, delegation}
   285  }
   286  
   287  func (pae PrincipalAlignmentError) Error() string {
   288  	return fmt.Sprintf("Delegation audience is '%s' instead of '%s'", pae.delegation.Audience().DID(), pae.audience.DID())
   289  }
   290  
   291  func (pae PrincipalAlignmentError) isInvalidProof() {}
   292  
   293  // InvalidCapability is an error produced when parsing capabilities.
   294  type InvalidCapability interface {
   295  	failure.Failure
   296  	isInvalidCapability()
   297  }
   298  
   299  type MalformedCapability interface {
   300  	InvalidCapability
   301  	DelegationSubError
   302  	Capability() ucan.Capability[any]
   303  	isMalformedCapability()
   304  }
   305  
   306  type MalformedCapabilityError struct {
   307  	failure.NamedWithStackTrace
   308  	capability ucan.Capability[any]
   309  	cause      error
   310  }
   311  
   312  func NewMalformedCapabilityError(capability ucan.Capability[any], cause error) MalformedCapability {
   313  	return MalformedCapabilityError{failure.NamedWithCurrentStackTrace("MalformedCapability"), capability, cause}
   314  }
   315  
   316  func (mce MalformedCapabilityError) Error() string {
   317  	capabilityJSON, _ := json.Marshal(mce.capability)
   318  	return strings.Join([]string{
   319  		fmt.Sprintf("Encountered malformed '%s' capability: %s", mce.capability.Can(), string(capabilityJSON)),
   320  		li(mce.cause.Error()),
   321  	}, "\n")
   322  }
   323  
   324  func (mce MalformedCapabilityError) Capability() ucan.Capability[any] {
   325  	return mce.capability
   326  }
   327  
   328  func (mce MalformedCapabilityError) isMalformedCapability() {}
   329  func (mce MalformedCapabilityError) isInvalidCapability()   {}
   330  func (mce MalformedCapabilityError) isDelegationSubError()  {}
   331  
   332  type UnknownCapability interface {
   333  	InvalidCapability
   334  	Capability() ucan.Capability[any]
   335  	isUnknownCapability()
   336  }
   337  
   338  type UnknownCapabilityError struct {
   339  	failure.NamedWithStackTrace
   340  	capability ucan.Capability[any]
   341  }
   342  
   343  func NewUnknownCapabilityError(capability ucan.Capability[any]) UnknownCapability {
   344  	return UnknownCapabilityError{failure.NamedWithCurrentStackTrace("UnknownCapability"), capability}
   345  }
   346  
   347  func (uce UnknownCapabilityError) Error() string {
   348  	capabilityJSON, _ := json.Marshal(uce.capability)
   349  	return fmt.Sprintf("Encountered unknown capability: %s", string(capabilityJSON))
   350  }
   351  
   352  func (uce UnknownCapabilityError) Capability() ucan.Capability[any] {
   353  	return uce.capability
   354  }
   355  
   356  func (uce UnknownCapabilityError) isUnknownCapability()  {}
   357  func (uce UnknownCapabilityError) isInvalidCapability()  {}
   358  func (uce UnknownCapabilityError) isDelegationSubError() {}
   359  
   360  type ExpiredError struct {
   361  	failure.NamedWithStackTrace
   362  	delegation delegation.Delegation
   363  }
   364  
   365  func NewExpiredError(delegation delegation.Delegation) InvalidProof {
   366  	return ExpiredError{failure.NamedWithCurrentStackTrace("Expired"), delegation}
   367  }
   368  
   369  func (ee ExpiredError) Error() string {
   370  	exp := ee.delegation.Expiration()
   371  	return fmt.Sprintf("Proof %s has expired on %s", ee.delegation.Link(),
   372  		time.Unix(int64(*exp), 0).Format(time.RFC3339))
   373  }
   374  
   375  func (ee ExpiredError) ToIPLD() (datamodel.Node, error) {
   376  	name := ee.Name()
   377  	stack := ee.Stack()
   378  	exp := ee.delegation.Expiration()
   379  	expiredModel := vdm.ExpiredModel{
   380  		Name:      &name,
   381  		Message:   ee.Error(),
   382  		ExpiredAt: int64(*exp),
   383  		Stack:     &stack,
   384  	}
   385  	return ipld.WrapWithRecovery(expiredModel, vdm.ExpiredType())
   386  }
   387  
   388  func (ee ExpiredError) isInvalidProof() {}
   389  
   390  type Revoked interface {
   391  	InvalidProof
   392  	Delegation() delegation.Delegation
   393  	isRevoked()
   394  }
   395  
   396  type RevokedError struct {
   397  	failure.NamedWithStackTrace
   398  	delegation delegation.Delegation
   399  }
   400  
   401  func NewRevokedError(delegation delegation.Delegation) Revoked {
   402  	return RevokedError{failure.NamedWithCurrentStackTrace("Revoked"), delegation}
   403  }
   404  
   405  func (re RevokedError) Delegation() delegation.Delegation {
   406  	return re.delegation
   407  }
   408  
   409  func (re RevokedError) Error() string {
   410  	return fmt.Sprintf("Proof %s has been revoked", re.delegation.Link())
   411  }
   412  
   413  func (re RevokedError) isInvalidProof() {}
   414  func (re RevokedError) isRevoked()      {}
   415  
   416  type NotValidBeforeError struct {
   417  	failure.NamedWithStackTrace
   418  	delegation delegation.Delegation
   419  }
   420  
   421  func NewNotValidBeforeError(delegation delegation.Delegation) InvalidProof {
   422  	return NotValidBeforeError{failure.NamedWithCurrentStackTrace("NotValidBefore"), delegation}
   423  }
   424  
   425  func (nvbe NotValidBeforeError) Error() string {
   426  	return fmt.Sprintf("Proof %s is not valid before %s", nvbe.delegation.Link(),
   427  		time.Unix(int64(nvbe.delegation.NotBefore()), 0).Format(time.RFC3339))
   428  }
   429  
   430  func (nvbe NotValidBeforeError) ToIPLD() (datamodel.Node, error) {
   431  	name := nvbe.Name()
   432  	stack := nvbe.Stack()
   433  	notValidBeforeModel := vdm.NotValidBeforeModel{
   434  		Name:    &name,
   435  		Message: nvbe.Error(),
   436  		ValidAt: int64(nvbe.delegation.NotBefore()),
   437  		Stack:   &stack,
   438  	}
   439  	return ipld.WrapWithRecovery(notValidBeforeModel, vdm.NotValidBeforeType())
   440  }
   441  
   442  func (nvbe NotValidBeforeError) isInvalidProof() {}
   443  
   444  type InvalidClaim interface {
   445  	failure.Failure
   446  	Issuer() ucan.Principal
   447  	Delegation() delegation.Delegation
   448  }
   449  
   450  type InvalidClaimError[Caveats any] struct {
   451  	failure.NamedWithStackTrace
   452  	match               Match[Caveats]
   453  	delegationErrors    []DelegationError
   454  	unknownCapabilities []ucan.Capability[any]
   455  	invalidProofs       []ProofError
   456  	failedProofs        []InvalidClaim
   457  }
   458  
   459  func NewInvalidClaimError[Caveats any](
   460  	match Match[Caveats],
   461  	delegationErrors []DelegationError,
   462  	unknownCapabilities []ucan.Capability[any],
   463  	invalidProofs []ProofError,
   464  	failedProofs []InvalidClaim,
   465  ) InvalidClaim {
   466  	return InvalidClaimError[Caveats]{
   467  		failure.NamedWithCurrentStackTrace("InvalidClaim"),
   468  		match,
   469  		delegationErrors,
   470  		unknownCapabilities,
   471  		invalidProofs,
   472  		failedProofs,
   473  	}
   474  }
   475  
   476  func (ice InvalidClaimError[Caveats]) Error() string {
   477  	errorStrings := make([]string, 0, len(ice.failedProofs)+len(ice.delegationErrors)+len(ice.invalidProofs))
   478  
   479  	for _, failedProof := range ice.failedProofs {
   480  		errorStrings = append(errorStrings, li(failedProof.Error()))
   481  	}
   482  
   483  	for _, delegationError := range ice.delegationErrors {
   484  		errorStrings = append(errorStrings, li(delegationError.Error()))
   485  	}
   486  
   487  	for _, invalidProof := range ice.invalidProofs {
   488  		errorStrings = append(errorStrings, li(invalidProof.Error()))
   489  	}
   490  
   491  	unknowns := make([]string, 0, len(ice.unknownCapabilities))
   492  	for _, unknownCapability := range ice.unknownCapabilities {
   493  		out, _ := unknownCapability.MarshalJSON()
   494  		unknowns = append(unknowns, li(string(out)))
   495  	}
   496  
   497  	var finalList []string
   498  	finalList = append(finalList, fmt.Sprintf("Capability %s is not authorized because:", ice.match))
   499  	finalList = append(finalList, li(fmt.Sprintf("Capability can not be (self) issued by '%s'", ice.Issuer().DID())))
   500  	if len(errorStrings) > 0 {
   501  		finalList = append(finalList, errorStrings...)
   502  	} else {
   503  		finalList = append(finalList, li("Delegated capability not found"))
   504  	}
   505  	if len(unknowns) > 0 {
   506  		finalList = append(finalList, li(fmt.Sprintf("Encountered unknown capabilities\n%s", strings.Join(unknowns, "\n"))))
   507  	}
   508  
   509  	return strings.Join(finalList, "\n")
   510  }
   511  
   512  func (ice InvalidClaimError[Caveats]) Issuer() ucan.Principal {
   513  	return ice.Delegation().Issuer()
   514  }
   515  
   516  func (ice InvalidClaimError[Caveats]) Delegation() delegation.Delegation {
   517  	return ice.match.Source()[0].Delegation()
   518  }
   519  
   520  func (ice InvalidClaimError[Caveats]) DelegationErrors() []DelegationError {
   521  	return ice.delegationErrors
   522  }
   523  
   524  func (ice InvalidClaimError[Caveats]) UnknownCapabilities() []ucan.Capability[any] {
   525  	return ice.unknownCapabilities
   526  }
   527  
   528  func (ice InvalidClaimError[Caveats]) InvalidProofs() []ProofError {
   529  	return ice.invalidProofs
   530  }
   531  
   532  func (ice InvalidClaimError[Caveats]) FailedProofs() []InvalidClaim {
   533  	return ice.failedProofs
   534  }
   535  
   536  type Unauthorized interface {
   537  	failure.Failure
   538  	DelegationErrors() []DelegationError
   539  	UnknownCapabilities() []ucan.Capability[any]
   540  	InvalidProofs() []InvalidProof
   541  	FailedProofs() []InvalidClaim
   542  	isUnauthorized()
   543  }
   544  
   545  type UnauthorizedError[Caveats any] struct {
   546  	failure.NamedWithStackTrace
   547  	capability       CapabilityParser[Caveats]
   548  	delegationErrors []DelegationError
   549  	// this is a hack... it will allow you to make an array of capabilities of different types
   550  	unknownCapabilities []ucan.Capability[any]
   551  	invalidProofs       []InvalidProof
   552  	failedProofs        []InvalidClaim
   553  }
   554  
   555  func NewUnauthorizedError[Caveats any](
   556  	capability CapabilityParser[Caveats],
   557  	delegationErrors []DelegationError,
   558  	unknownCapabilities []ucan.Capability[any],
   559  	invalidProofs []InvalidProof,
   560  	failedProofs []InvalidClaim,
   561  ) Unauthorized {
   562  	return UnauthorizedError[Caveats]{
   563  		failure.NamedWithCurrentStackTrace("Unauthorized"),
   564  		capability,
   565  		delegationErrors,
   566  		unknownCapabilities,
   567  		invalidProofs,
   568  		failedProofs,
   569  	}
   570  }
   571  
   572  func (ue UnauthorizedError[Caveats]) Error() string {
   573  	errorStrings := make([]string, 0, len(ue.failedProofs)+len(ue.delegationErrors)+len(ue.invalidProofs))
   574  
   575  	for _, failedProof := range ue.failedProofs {
   576  		errorStrings = append(errorStrings, li(failedProof.Error()))
   577  	}
   578  
   579  	for _, delegationError := range ue.delegationErrors {
   580  		errorStrings = append(errorStrings, li(delegationError.Error()))
   581  	}
   582  
   583  	for _, invalidProof := range ue.invalidProofs {
   584  		errorStrings = append(errorStrings, li(invalidProof.Error()))
   585  	}
   586  
   587  	unknowns := make([]string, 0, len(ue.unknownCapabilities))
   588  	for _, unknownCapability := range ue.unknownCapabilities {
   589  		out, _ := unknownCapability.MarshalJSON()
   590  		unknowns = append(unknowns, li(string(out)))
   591  	}
   592  
   593  	finalList := make([]string, 0, 2+int(math.Min(1, float64(len(errorStrings)))))
   594  	finalList = append(finalList, fmt.Sprintf("Claim %s is not authorized", ue.capability))
   595  	if len(errorStrings) > 0 {
   596  		finalList = append(finalList, errorStrings...)
   597  	} else {
   598  		finalList = append(finalList, li("No matching delegated capability found"))
   599  	}
   600  	if len(unknowns) > 0 {
   601  		finalList = append(finalList, li(fmt.Sprintf("Encountered unknown capabilities\n%s", strings.Join(unknowns, "\n"))))
   602  	}
   603  
   604  	return strings.Join(finalList, "\n")
   605  }
   606  
   607  func (ue UnauthorizedError[Caveats]) DelegationErrors() []DelegationError {
   608  	return ue.delegationErrors
   609  }
   610  
   611  func (ue UnauthorizedError[Caveats]) UnknownCapabilities() []ucan.Capability[any] {
   612  	return ue.unknownCapabilities
   613  }
   614  
   615  func (ue UnauthorizedError[Caveats]) InvalidProofs() []InvalidProof {
   616  	return ue.invalidProofs
   617  }
   618  
   619  func (ue UnauthorizedError[Caveats]) FailedProofs() []InvalidClaim {
   620  	return ue.failedProofs
   621  }
   622  
   623  func (ue UnauthorizedError[Caveats]) isUnauthorized() {}
   624  
   625  func indent(message string) string {
   626  	indent := "  "
   627  	return indent + strings.Join(strings.Split(message, "\n"), "\n"+indent)
   628  }
   629  
   630  func li(message string) string {
   631  	return indent("- " + message)
   632  }
   633  
   634  type ProofError struct {
   635  	failure.NamedWithStackTrace
   636  	proof ucan.Link
   637  	cause error
   638  }
   639  
   640  func (pe ProofError) Error() string {
   641  	return fmt.Sprintf("Capability can not be derived from prf: %s because:\n%s", pe.proof, li(pe.cause.Error()))
   642  }
   643  
   644  func (pe ProofError) Proof() ucan.Link {
   645  	return pe.proof
   646  }
   647  
   648  func (pe ProofError) Unwrap() error {
   649  	return pe.cause
   650  }
   651  
   652  func NewProofError(proof ucan.Link, cause error) ProofError {
   653  	return ProofError{failure.NamedWithCurrentStackTrace("ProofError"), proof, cause}
   654  }