Skip to content

feat(signature): add org.accordproject.signature@1.0.0 - #195

Open
niallroche wants to merge 1 commit into
accordproject:mainfrom
niallroche:agent/signature-model
Open

feat(signature): add org.accordproject.signature@1.0.0#195
niallroche wants to merge 1 commit into
accordproject:mainfrom
niallroche:agent/signature-model

Conversation

@niallroche

Copy link
Copy Markdown
Contributor

Closes #<N/A>

Reposition org.accordproject.signature from a narrow ContractSigned transaction into a general model of verifiable attestations over contract and agreement content.

Changes

  • Add org.accordproject.signature@1.0.0.
  • Add the Attestation envelope, Signatory, ValidityWindow, Delegation, AttestationStatus, SignatureMethod, and AssuranceLevel.
  • Add an abstract Proof concept with OpaqueProof as an escape hatch for protocol-specific proof formats.
  • Bind attested content via org.accordproject.crypto@1.0.0.ContentHash, so attestations carry digest algorithm, value, encoding, and optional canonicalization metadata rather than a bare string.
  • Keep the existing ContractSigned extends Request transaction and enrich it with optional Attestation[] data, giving older consumers a familiar migration path while newer integrations can inspect structured signature metadata.

Flags

  • This is a 1.0.0 version because the signature namespace is being repositioned from a narrow transaction model into a stable signature/attestation model.
  • Runtime and contract imports intentionally remain aligned with signature@0.3.0 for compatibility.
  • Part of the agentic-commerce model family alongside crypto and x402, with a2a/ap2 to follow.
  • Aligns with the reference-implementation signing work in accordproject/apap#182.

Screenshots or Video

N/A

Related Issues

Author Checklist

  • Ensure you provide a DCO sign-off for your commits using the --signoff option of git commit.
  • Vital features and changes captured in unit and/or integration tests
  • Commits messages follow AP format
  • Extend the documentation, if necessary
  • Merging to master from fork:branchname

Reposition org.accordproject.signature from a narrow ContractSigned transaction into a general model of verifiable attestations over contract and agreement content.

Adds the Attestation envelope, Signatory, ValidityWindow, Delegation, AttestationStatus, SignatureMethod, AssuranceLevel, and an abstract Proof with OpaqueProof as an escape hatch for protocol-specific proof formats.

Content is bound via org.accordproject.crypto@1.0.0.ContentHash from the published crypto model, so attestations carry digest algorithm, value, encoding, and optional canonicalization metadata rather than a bare string.

Keeps the ContractSigned extends Request transaction from earlier signature versions and enriches it with optional Attestation[] data, so older consumers have a familiar migration path while newer integrations can inspect structured signature metadata.

Part of the agentic-commerce model family alongside crypto and x402, with a2a/ap2 to follow. Aligns with the reference-implementation signing work in accordproject/apap#182.

Signed-off-by: Niall Roche <niall.roche@gmail.com>
@mttrbrts

mttrbrts commented Aug 5, 2026

Copy link
Copy Markdown
Member

Great work on this model — a few suggestions for consideration:

Typed proof subtypes

OpaqueProof works as an escape hatch, but a ProviderProof extends Proof with structured fields for common evidence would make verification more tractable:

concept ProviderProof extends Proof {
    o String providerId          // e.g. "docusign", "adobe-sign", "wet-ink"
    o String envelopeOrSessionId optional  // provider's transaction/session identifier
    o String recipientId optional          // provider's per-recipient identifier
    o String certificateUri optional       // URL to provider-issued certificate
    o String ipAddress optional            // signer's IP at time of signing
    o String userAgent optional            // browser/device context
}

For DocuSign this maps directly: providerId: "docusign", envelopeOrSessionId holds the envelope UUID, certificateUri points to the Certificate of Completion. Other providers (Adobe Sign, HelloSign, wet-ink scan workflows) would populate the same fields differently.

Identity verification method

AssuranceLevel captures the tier of assurance but not the mechanism used to verify identity before signing. Providers record this granularly and it directly supports assurance level claims:

enum IdentityVerificationMethod {
    o EMAIL_LINK
    o SMS_OTP
    o PHONE_CALL
    o KNOWLEDGE_BASED_AUTH
    o ID_DOCUMENT_SCAN
    o ACCESS_CODE
    o NONE
    o CUSTOM
}

concept IdentityVerification {
    o IdentityVerificationMethod method
    o DateTime verifiedAt optional
    o String providerId optional
    o String customName optional
}

Add o IdentityVerification identityVerification optional to Attestation. DocuSign's ID Verify maps to ID_DOCUMENT_SCAN; standard email-link signing maps to EMAIL_LINK. This makes the backing evidence for ADVANCED vs STANDARD assurance explicit rather than implied.

Status decline/revocation reason

AttestationStatus has REVOKED but no way to record why. Providers capture decline reasons verbatim:

concept AttestationStatusDetail {
    o AttestationStatus status
    o String reason optional
    o DateTime timestamp optional
}

Replace o AttestationStatus status default="CREATED" on Attestation with o AttestationStatusDetail status.

Multi-document support

A single ContentHash per attestation assumes one document per signing action. Many providers bundle multiple documents into one signing event (envelopes, signing packages). Wrapping it allows a signer's single action to cover multiple documents:

concept DocumentAttestation {
    o String documentId optional    // provider's document sequence/ID within the bundle
    o String documentName optional
    o ContentHash contentHash
}

Replace o ContentHash contentHash on Attestation with o DocumentAttestation[] documents.


AP stack integration

Template archive reference on ContractSigned. The --> Contract contract relationship gives you the contract instance, and the CTO class implicitly encodes the template name. But the specific archive version (the .cta file) that produced the contract isn't captured. Two contracts can share the same CTO class but come from different archive versions with different logic or clause text. A small addition closes this:

concept TemplateReference {
    o String identifier        // e.g. "latedeliveryandpenalty"
    o String version           // e.g. "0.15.0"
    o ContentHash archiveHash optional  // hash of the .cta archive
}

transaction ContractSigned extends Request {
    --> Contract contract
    o TemplateReference template optional
    o Attestation[] attestations optional
}

Content representation. contentHash is ambiguous about what was hashed — Concerto JSON, rendered CiceroMark, plaintext, PDF. Signatories typically sign rendered text, not data models. An explicit field would let verifiers know what to re-hash:

enum ContentRepresentation {
    o CONCERTO_JSON
    o CICEROMARK
    o PLAINTEXT
    o PDF
    o CUSTOM
}

Add o ContentRepresentation contentRepresentation optional to DocumentAttestation (or ContentHash directly, though the latter has broader reuse implications).


Happy to elaborate on any of these or sketch out how they'd compose with the existing crypto@1.0.0 model.

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