Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

#### TAIP Spec Catch-Up (tap-msg, tap-ts)
- TAIP-17 `Lock` message type (renamed from `Escrow`); `Capture` and the `EscrowAgent` role string unchanged. `Escrow` retained as a `pub type` alias for `Lock`.
- TAIP-18 `Rfq` message type (renamed from `Exchange`); `Quote` unchanged. `Exchange` retained as a `pub type` alias for `Rfq`.
- TAIP-20 on-chain memo-hash helpers in `tap_msg::utils::memo_hash`: `tap_memo_hash`, `encode_text_memo`, `encode_binary_memo`, `verify_text_memo`, `verify_binary_memo`. Implements the canonical `tap:1:<64-hex>` text profile and 32-byte binary profile per `SHA-256(transfer_id)`.
- `TapMessage::from_plain_message` now accepts both legacy and new URIs (`#Escrow` and `#Lock` → `TapMessage::Lock`; `#Exchange` and `#RFQ` → `TapMessage::Rfq`).
- `tap-ts`: bumped `@taprsvp/types` from `^1.9.0` to `^2.1.0`. Added `Lock`/`RFQ` exports alongside `Escrow`/`Exchange` aliases. New `createRfqMessage` helper; `createExchangeMessage` retained as an alias.

### Changed
- Outgoing `Lock` and `Rfq` messages emit the new canonical URIs (`#Lock` / `#RFQ`).
- Internal clippy fix: `tap-agent::verification` matches now use match guards instead of nested `if` to satisfy `clippy::collapsible-match` on newer rustc.

#### External Secret Helper for Key Management (tap-agent, tap-cli, tap-http, tap-mcp)
- Git-like secret helper pattern for retrieving private keys from external stores (HashiCorp Vault, AWS KMS, 1Password)
- `get_private_key(did)` method on `AgentKeyManager` and `KeyManager` trait
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ members = [
resolver = "2"

[workspace.package]
version = "0.6.0"
version = "0.7.0"
edition = "2021"
authors = ["Pelle Braendgaard <pelle@notabene.id>"]
description = "Rust implementation of the Transaction Authorization Protocol (TAP)"
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

This repository contains a Rust implementation of the Transaction Authorization Protocol (TAP), a decentralized protocol for securely authorizing blockchain transactions before they are submitted on-chain. TAP-RS targets payment-related use cases, Travel Rule compliance, and secure transaction coordination.

**New in v0.7.0**:
- TAIP-17 `Lock` (renamed from `Escrow`) and TAIP-18 `Rfq` (renamed from `Exchange`); old type names retained as aliases and legacy URIs accepted on the wire
- TAIP-20 on-chain memo-hash helpers (`tap_msg::utils::memo_hash`) for `SHA-256(transfer_id)` settlement correlation
- `tap-ts` upgraded to `@taprsvp/types` v2.1
- External secret helper (Vault / AWS KMS / 1Password) for private key retrieval in `tap-agent`, `tap-cli`, `tap-http`, `tap-mcp`
- Flattened JWS serialization for Veramo compatibility
- X25519 JWE anoncrypt support

**New in v0.6.0**:
- External decision executable support for pluggable authorization workflows
- Poll mode for decision management via MCP tools
Expand Down
2 changes: 1 addition & 1 deletion prds/taips
Submodule taips updated 55 files
+1 −0 .gitignore
+1 −0 .mdlrc
+138 −42 CHANGELOG.md
+9 −0 Gemfile
+21 −0 Gemfile.lock
+7 −3 README.md
+2 −2 TAIPs/taip-1.md
+106 −24 TAIPs/taip-14.md
+277 −53 TAIPs/taip-15.md
+29 −29 TAIPs/taip-17.md
+690 −0 TAIPs/taip-18.md
+605 −0 TAIPs/taip-19.md
+188 −0 TAIPs/taip-20.md
+52 −6 TAIPs/taip-3.md
+2 −2 TAIPs/taip-4.md
+1 −1 _config.yml
+13 −8 _includes/blurb.html
+1 −23 _includes/head.html
+21 −32 _layouts/default.html
+44 −40 _layouts/taip.html
+8 −0 assets/apple-touch-icon.svg
+474 −313 assets/css/main.css
+8 −0 assets/favicon.svg
+289 −0 assets/js/mermaid-theme.js
+89 −2 developers.md
+135 −80 index.html
+79 −0 llms.txt
+342 −67 messages.md
+0 −350 packages/typescript/README.md
+0 −2,069 packages/typescript/package-lock.json
+0 −42 packages/typescript/package.json
+0 −319 packages/typescript/src/currencies.ts
+0 −5 packages/typescript/src/index.ts
+0 −446 packages/typescript/src/invoice.ts
+0 −211 packages/typescript/src/nameHash.test.ts
+0 −102 packages/typescript/src/nameHash.ts
+0 −780 packages/typescript/src/purpose_codes.ts
+0 −1,928 packages/typescript/src/tap.ts
+0 −17 packages/typescript/tsconfig.json
+82 −35 schemas/data-structures/transaction-constraints.json
+1 −1 schemas/messages/capture.json
+31 −30 schemas/messages/connect.json
+5 −5 schemas/messages/lock.json
+89 −0 schemas/messages/quote.json
+112 −0 schemas/messages/rfq.json
+15 −0 schemas/messages/transfer.json
+11 −5 test-vectors/connect/invalid-missing-constraints.json
+33 −8 test-vectors/connect/valid-b2b-connect.json
+5 −5 test-vectors/lock/invalid-missing-beneficiary.json
+14 −4 test-vectors/lock/valid-lock.json
+1 −1 test-vectors/out-of-band/valid-connect-oob.json
+11 −5 test-vectors/payment-request/valid-payment-fiat.json
+11 −5 test-vectors/payment-request/valid-payment.json
+7 −2 test-vectors/payment-request/valid-payto-invoice.json
+57 −11 transactions.md
4 changes: 2 additions & 2 deletions tap-agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ license.workspace = true
readme = "README.md"

[dependencies]
tap-msg = { version = "0.6.0", path = "../tap-msg" }
tap-caip = { version = "0.6.0", path = "../tap-caip" }
tap-msg = { version = "0.7.0", path = "../tap-msg" }
tap-caip = { version = "0.7.0", path = "../tap-caip" }
async-trait = { workspace = true }
thiserror = "1.0"
serde = { workspace = true }
Expand Down
36 changes: 15 additions & 21 deletions tap-agent/src/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,11 @@ fn verify_eddsa(
} => {
// Decode the multibase key
match multibase::decode(public_key_multibase) {
Ok((Base::Base58Btc, key_data)) => {
// Skip the multicodec prefix (0xed01 for Ed25519)
if key_data.len() >= 34 && key_data[0] == 0xed && key_data[1] == 0x01 {
key_data[2..].to_vec()
} else {
return false;
}
// Skip the multicodec prefix (0xed01 for Ed25519)
Ok((Base::Base58Btc, key_data))
if key_data.len() >= 34 && key_data[0] == 0xed && key_data[1] == 0x01 =>
{
key_data[2..].to_vec()
}
_ => return false,
}
Expand Down Expand Up @@ -214,13 +212,11 @@ fn verify_es256(
} => {
// Decode the multibase key
match multibase::decode(public_key_multibase) {
Ok((Base::Base58Btc, key_data)) => {
// Skip the multicodec prefix (0x1200 for P-256)
if key_data.len() >= 67 && key_data[0] == 0x12 && key_data[1] == 0x00 {
key_data[2..].to_vec()
} else {
return false;
}
// Skip the multicodec prefix (0x1200 for P-256)
Ok((Base::Base58Btc, key_data))
if key_data.len() >= 67 && key_data[0] == 0x12 && key_data[1] == 0x00 =>
{
key_data[2..].to_vec()
}
_ => return false,
}
Expand Down Expand Up @@ -265,13 +261,11 @@ fn verify_es256k(
} => {
// Decode the multibase key
match multibase::decode(public_key_multibase) {
Ok((Base::Base58Btc, key_data)) => {
// Skip the multicodec prefix (0xe701 for secp256k1)
if key_data.len() >= 67 && key_data[0] == 0xe7 && key_data[1] == 0x01 {
key_data[2..].to_vec()
} else {
return false;
}
// Skip the multicodec prefix (0xe701 for secp256k1)
Ok((Base::Base58Btc, key_data))
if key_data.len() >= 67 && key_data[0] == 0xe7 && key_data[1] == 0x01 =>
{
key_data[2..].to_vec()
}
_ => return false,
}
Expand Down
16 changes: 8 additions & 8 deletions tap-agent/tests/test_vectors_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use std::fs;
use std::path::Path;
use tap_msg::didcomm::PlainMessage;
use tap_msg::message::{
AuthorizationRequired, Cancel, ConfirmRelationship, Connect, DIDCommPresentation, Escrow,
AuthorizationRequired, Cancel, ConfirmRelationship, Connect, DIDCommPresentation, Lock,
Payment, RemoveAgent, ReplaceAgent, Revert, UpdateParty, UpdatePolicies,
};
use tap_msg::{
Expand Down Expand Up @@ -298,17 +298,17 @@ fn validate_tap_message(message: &PlainMessage) -> Result<(), String> {
.map_err(|e| format!("Failed to parse AuthorizationRequired: {}", e))?;
auth_required.validate().map_err(|e| e.to_string())
}
"https://tap.rsvp/schema/1.0#Escrow" => {
// Create a more lenient Escrow parsing by fixing agents
// TAIP-17 was renamed Escrow → Lock; both URIs dispatch to `Lock`.
"https://tap.rsvp/schema/1.0#Lock" | "https://tap.rsvp/schema/1.0#Escrow" => {
// Test vectors sometimes omit `for` on the EscrowAgent; default it
// to the agent's own DID before parsing.
let mut clean_body = body_with_thread_id.clone();
if let Some(obj) = clean_body.as_object_mut() {
// Fix agents by adding missing 'for' field if needed
if let Some(agents) = obj.get_mut("agents") {
if let Some(agents_array) = agents.as_array_mut() {
for agent in agents_array.iter_mut() {
if let Some(agent_obj) = agent.as_object_mut() {
if !agent_obj.contains_key("for") {
// For escrow agents, default to acting for themselves
if let Some(agent_id) = agent_obj.get("@id") {
agent_obj.insert("for".to_string(), agent_id.clone());
}
Expand All @@ -319,9 +319,9 @@ fn validate_tap_message(message: &PlainMessage) -> Result<(), String> {
}
}

let escrow: Escrow = serde_json::from_value(clean_body)
.map_err(|e| format!("Failed to parse Escrow: {}", e))?;
escrow.validate().map_err(|e| e.to_string())
let lock: Lock = serde_json::from_value(clean_body)
.map_err(|e| format!("Failed to parse Lock: {}", e))?;
lock.validate().map_err(|e| e.to_string())
}
"https://didcomm.org/out-of-band/2.0/invitation" => {
// Out-of-band messages must have a goal_code starting with "tap."
Expand Down
8 changes: 4 additions & 4 deletions tap-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ path = "src/lib.rs"

[dependencies]
# TAP ecosystem dependencies
tap-node = { version = "0.6.0", path = "../tap-node" }
tap-agent = { version = "0.6.0", path = "../tap-agent" }
tap-msg = { version = "0.6.0", path = "../tap-msg" }
tap-caip = { version = "0.6.0", path = "../tap-caip" }
tap-node = { version = "0.7.0", path = "../tap-node" }
tap-agent = { version = "0.7.0", path = "../tap-agent" }
tap-msg = { version = "0.7.0", path = "../tap-msg" }
tap-caip = { version = "0.7.0", path = "../tap-caip" }

# Async runtime and I/O
tokio = { version = "1.0", features = ["full"] }
Expand Down
10 changes: 5 additions & 5 deletions tap-http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ description = "HTTP server for the Transaction Authorization Protocol (TAP)"
readme = "README.md"

[dependencies]
tap-msg = { version = "0.6.0", path = "../tap-msg" }
tap-node = { version = "0.6.0", path = "../tap-node", features = ["storage"] }
tap-agent = { version = "0.6.0", path = "../tap-agent" }
tap-caip = { version = "0.6.0", path = "../tap-caip" }
tap-msg = { version = "0.7.0", path = "../tap-msg" }
tap-node = { version = "0.7.0", path = "../tap-node", features = ["storage"] }
tap-agent = { version = "0.7.0", path = "../tap-agent" }
tap-caip = { version = "0.7.0", path = "../tap-caip" }
warp = "0.3"
tokio = { workspace = true, features = ["full"] }
serde = { workspace = true }
Expand All @@ -36,7 +36,7 @@ base64 = { workspace = true }
multibase = { workspace = true }
dirs = "6.0"

tap-mcp = { version = "0.6.0", path = "../tap-mcp" }
tap-mcp = { version = "0.7.0", path = "../tap-mcp" }
tracing-subscriber = "0.3"

[dev-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion tap-ivms101/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ chrono = { version = "0.4", features = ["serde"] }
thiserror = "1.0"
iso_currency = "0.4"
regex = "1.5"
tap-msg = { version = "0.6.0", path = "../tap-msg" }
tap-msg = { version = "0.7.0", path = "../tap-msg" }

[dev-dependencies]
tokio = { version = "1.39", features = ["full"] }
Expand Down
8 changes: 4 additions & 4 deletions tap-mcp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ path = "src/main.rs"

[dependencies]
# TAP ecosystem dependencies
tap-node = { version = "0.6.0", path = "../tap-node" }
tap-agent = { version = "0.6.0", path = "../tap-agent" }
tap-msg = { version = "0.6.0", path = "../tap-msg" }
tap-caip = { version = "0.6.0", path = "../tap-caip" }
tap-node = { version = "0.7.0", path = "../tap-node" }
tap-agent = { version = "0.7.0", path = "../tap-agent" }
tap-msg = { version = "0.7.0", path = "../tap-msg" }
tap-caip = { version = "0.7.0", path = "../tap-caip" }

# Async runtime and I/O
tokio = { version = "1.0", features = ["full"] }
Expand Down
4 changes: 2 additions & 2 deletions tap-msg/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ serde = { workspace = true }
serde_json = { workspace = true }

# Chain Agnostic Identifiers
tap-caip = { version = "0.6.0", path = "../tap-caip" }
tap-caip = { version = "0.7.0", path = "../tap-caip" }

# Date and time
chrono = { workspace = true }
Expand All @@ -36,7 +36,7 @@ uuid = { workspace = true }
tracing = { workspace = true }

# Derive macro for TAP messages
tap-msg-derive = { version = "0.6.0", path = "../tap-msg-derive" }
tap-msg-derive = { version = "0.7.0", path = "../tap-msg-derive" }

# WASM support
wasm-bindgen = { workspace = true, optional = true }
Expand Down
Loading
Loading