Skip to content

Latest commit

 

History

History
234 lines (184 loc) · 6.54 KB

File metadata and controls

234 lines (184 loc) · 6.54 KB

TFEP B2B Document Exchange

Send invoices, purchase orders, and contracts between businesses with cryptographic sender identity and permit-based authorization — no EDI VANs required.


Overview

Traditional B2B document exchange (EDI, AS2, SFTP) solves the wrong problem: it focuses on transport security (encrypting the pipe) but ignores sender identity. Anyone with SFTP credentials can send any file. TFEP solves this:

  • Invoices are signed by did:web:vendor.com — unforgeable, auditable
  • Permit system authorizes specific vendors to send invoices to your gateway
  • Delivery receipts confirm the document reached the buyer's gateway
  • Audit trail in SQLite: every document stored with full TFEP envelope

Document Types

TFEP Type Use case
invoice Accounts receivable — vendor → buyer
purchase_order Procurement — buyer → vendor
contract Legal agreements — any direction
receipt Delivery acknowledgment (auto-generated)

Sending a Document

Via REST API

curl -X POST http://localhost:8080/api/v1/documents/send \
  -H "Authorization: Bearer $TFEP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recipient_did": "did:web:buyer.example",
    "type": "invoice",
    "subject": "Invoice INV-2026-042 — $12,500 USD",
    "body": "Dear Buyer,\n\nPlease find attached invoice INV-2026-042...",
    "metadata": {
      "invoice_number": "INV-2026-042",
      "issue_date": "2026-05-31",
      "due_date": "2026-06-30",
      "amount": 12500.00,
      "currency": "USD",
      "vendor_id": "ACME-001",
      "po_reference": "PO-2026-009",
      "line_items": [
        { "description": "Software licenses Q3", "quantity": 5, "unit_price": 2500.00, "total": 12500.00 }
      ]
    }
  }'

Response:

{"status": "sent", "message_id": "550e8400-e29b-41d4-a716-446655440000"}

The document is:

  1. Wrapped in a TFEP envelope with type: invoice, sender_did: did:web:your-gateway.com
  2. Signed with your gateway's Ed25519 private key
  3. Delivered to the buyer's SMTP/TFEP gateway (MX lookup)
  4. Stored locally as direction: outbound

Via CLI (uses the send command)

./tfep-gateway send \
  --to accounts@buyer.example \
  --type invoice \
  --subject "Invoice INV-2026-042" \
  --body "Payment due 30 days from invoice date."

Via Go (direct library use)

import (
    "github.com/tfep/tfep-gateway/internal/smtp"
    "github.com/tfep/tfep-gateway/pkg/tfep"
    "encoding/json"
)

meta, _ := json.Marshal(map[string]any{
    "invoice_number": "INV-2026-042",
    "amount": 12500.00,
    "currency": "USD",
})

env := tfep.Envelope{
    Version:      "1",
    MessageID:    uuid.New().String(),
    MessageType:  tfep.TypeInvoice,
    SenderDID:    "did:web:vendor.example",
    RecipientDID: "did:web:buyer.example",
    Timestamp:    time.Now().UTC(),
    Subject:      "Invoice INV-2026-042",
    Metadata:     meta,
}
smtp.Send(cfg, smtp.SendOptions{Envelope: env, Body: body, SigningKey: priv})

Receiving Documents

Inbound (SMTP path)

When a buyer's gateway receives an invoice via SMTP:

  1. The SMTP server extracts the TFEP envelope from the MIME parts
  2. Resolves the sender's DID and verifies the Ed25519 signature
  3. Assigns a trust tier (Verified if signature passes)
  4. Stores the message with direction: inbound, message_type: invoice
  5. Available at GET /api/v1/documents?direction=inbound&type=invoice

Querying received documents

# All incoming invoices
curl -H "Authorization: Bearer $TFEP_API_KEY" \
  "http://localhost:8080/api/v1/documents?direction=inbound&type=invoice"

# Outbound purchase orders
curl -H "Authorization: Bearer $TFEP_API_KEY" \
  "http://localhost:8080/api/v1/documents?direction=outbound&type=purchase_order"

# Get a specific document with its metadata
curl -H "Authorization: Bearer $TFEP_API_KEY" \
  "http://localhost:8080/api/v1/documents/{message-id}"

Permit-Based Vendor Authorization

Before a vendor can send you invoices (or any message type requiring authorization), issue them a permit:

# Issue a permit to vendor did:web:acme.com, valid for 1 year
curl -X POST http://localhost:8080/api/v1/permits \
  -H "Authorization: Bearer $TFEP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "grantee_did": "did:web:acme.com",
    "expiry_hours": 8760
  }'

The vendor includes the permit_token in their invoice envelope. Your gateway validates it before accepting the invoice. Invoices without a valid permit are held in the Unknown queue.

Permit lifecycle:

  • Issue → vendor can send (any invoice type message)
  • Revoke → vendor cannot send (immediate effect)
  • Expire → vendor cannot send (automatic after expiry_hours)

Metadata Schema

The metadata field accepts any JSON. Recommended fields for invoices:

{
  "invoice_number": "INV-2026-042",
  "issue_date": "2026-05-31",
  "due_date": "2026-06-30",
  "amount": 12500.00,
  "currency": "USD",
  "vendor_id": "ACME-001",
  "po_reference": "PO-2026-009",
  "payment_terms": "Net 30",
  "bank_account": "...",
  "line_items": [...]
}

For purchase orders:

{
  "po_number": "PO-2026-009",
  "issue_date": "2026-05-28",
  "delivery_date": "2026-06-15",
  "ship_to": "123 Main St, Springfield",
  "line_items": [...]
}

Audit Trail

Every document is stored in SQLite:

SELECT id, message_type, sender_did, recipient_did, subject, 
       document_meta, direction, received_at 
FROM messages 
WHERE message_type IN ('invoice', 'purchase_order', 'contract')
ORDER BY received_at DESC;

The full TFEP envelope (with Ed25519 signature) is stored in tfep_envelope — cryptographic proof that the document came from the claimed sender, at the claimed time, with unmodified content.


Full Working Example

# Send an invoice using the example program
go run ./examples/b2b-invoicing \
  --gateway http://localhost:8080 \
  --api-key $TFEP_API_KEY \
  --to did:web:buyer.example \
  --invoice-number INV-2026-001 \
  --amount 4999 \
  --currency USD

Compared to EDI / AS2

Feature EDI (AS2/SFTP) TFEP
Sender identity Directory configuration Cryptographic (Ed25519)
Forgeability Anyone with credentials Computationally infeasible
Infrastructure VAN / AS2 server Any SMTP gateway
Onboarding Days (manual config) Minutes (keygen + DNS TXT)
Format X12 / EDIFACT JSON + MIME
Audit trail VAN logs (external) Local SQLite (you own it)
Cost $500–$5000/month VAN fee Free (self-hosted)