Send non-repudiable notices with cryptographic proof of delivery — suitable for regulatory compliance, legal service of process, and audit notifications.
Email has no mechanism for:
- Proving who sent the notice (SMTP From is trivially spoofed)
- Proving the recipient received it (read receipts are unreliable and optional)
- Preventing the sender from later denying they sent it (repudiation)
TFEP solves all three:
- Who sent it: Ed25519 signature verifiable against the sender's DID document
- Delivery proof: Mandatory receipt automatically sent by the recipient's gateway
- Non-repudiation: Signed timestamp + message ID cannot be altered retroactively
curl -X POST http://localhost:8080/api/v1/notices/send \
-H "Authorization: Bearer $TFEP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"recipient_did": "did:web:respondent.example",
"subject": "Notice of Compliance Requirement — Case 2026-001",
"body": "Pursuant to Section 12(b) of the Data Act, you are hereby required...",
"metadata": {
"case_number": "CASE-2026-001",
"issuer": "Acme Regulatory Authority",
"issue_date": "2026-05-31",
"deadline": "2026-08-01",
"notice_type": "compliance",
"response_url": "https://portal.acme-authority.gov/respond/CASE-2026-001"
}
}'What happens:
- The gateway wraps the notice in a
legal_noticeTFEP envelope - Sets
request_receipt: true— the recipient is asked to send a receipt - Issues a permit so the recipient's gateway can send the receipt back
- Signs the envelope with the gateway's Ed25519 key
- Delivers via SMTP to the recipient's gateway (MX lookup)
- Stores locally as
direction: outbound
When the recipient's TFEP gateway receives the notice, it automatically sends a receipt message back to the sender. The receipt contains:
bounced_message_id— the ID of the original noticetimestamp— when the receipt was generated (at the recipient's gateway)sender_didof the recipient — proving who acknowledged it
The sender's gateway stores the receipt and links it to the original notice via receipt_message_id.
# Get the notice and its receipt (if received)
curl -H "Authorization: Bearer $TFEP_API_KEY" \
"http://localhost:8080/api/v1/notices/{notice-id}"Before receipt:
{
"notice": {
"id": "550e8400-...",
"subject": "Notice of Compliance...",
"direction": "outbound",
"receipt_message_id": ""
}
}After receipt:
{
"notice": {
"id": "550e8400-...",
"subject": "Notice of Compliance...",
"receipt_message_id": "7c9e6679-..."
},
"receipt": {
"id": "7c9e6679-...",
"message_type": "receipt",
"sender_did": "did:web:respondent.example",
"received_at": "2026-05-31T14:23:11Z"
}
}List all sent notices:
curl -H "Authorization: Bearer $TFEP_API_KEY" \
"http://localhost:8080/api/v1/notices?direction=outbound"A complete delivery proof consists of:
-
Original notice (stored locally):
- TFEP envelope:
message_id,sender_did,timestamp,body_hash - Ed25519 signature over the canonical envelope hash
- Your private key signs → your public key (in your DID document) verifies
- TFEP envelope:
-
Delivery receipt (stored locally, sent by recipient):
- TFEP envelope:
bounced_message_id= originalmessage_id,sender_didof recipient - Ed25519 signature by the recipient's key
- TFEP envelope:
Together, these two signed records prove:
- You sent notice
Xat timeTtodid:web:respondent.example - The respondent's gateway received and processed it at time
T2 - Neither party can alter the
message_id,timestamp, or content without breaking the signature
Recommended metadata schema for legal notices:
{
"case_number": "CASE-2026-001",
"issuer": "Acme Regulatory Authority",
"issue_date": "2026-05-31",
"deadline": "2026-08-01",
"notice_type": "compliance",
"response_url": "https://portal.example.gov/respond/CASE-2026-001",
"statute": "Data Act §12(b)",
"jurisdiction": "EU",
"confidential": false
}Notice types: compliance, subpoena, audit, regulatory, cease-and-desist, data-breach, gdpr-sar
# All outbound notices (sent by you)
curl -H "Authorization: Bearer $TFEP_API_KEY" \
"http://localhost:8080/api/v1/notices?direction=outbound"
# All inbound notices (received by you)
curl -H "Authorization: Bearer $TFEP_API_KEY" \
"http://localhost:8080/api/v1/notices?direction=inbound"
# Specific notice + receipt
curl -H "Authorization: Bearer $TFEP_API_KEY" \
"http://localhost:8080/api/v1/notices/{id}"A regulatory agency deploying TFEP for official notices:
1. Generate identity:
./tfep-gateway keygen --domain authority.gov2. Publish DID document:
Deploy the output JSON to https://authority.gov/.well-known/did.json. This is the public record of your signing key.
3. Add DNS record:
_tfep.authority.gov TXT "v=TFEP1; did=did:web:authority.gov; policy=bridge; caps=v1"
4. Configure:
# config.yaml
identity:
did: did:web:authority.gov
priv_key_file: ed25519.pem
trust:
send_receipts: true
auto_approve_permits: false # require explicit permits for inbound from regulated entities5. Send notices:
Use the REST API or the CLI send command. Every notice is automatically signed with did:web:authority.gov.
# Send notice and poll for receipt
go run ./examples/legal-notice \
--gateway http://localhost:8080 \
--api-key $TFEP_API_KEY \
--to did:web:respondent.example \
--subject "Notice of Audit — Case 2026-001" \
--body "You are required to provide documentation within 30 days." \
--case-number CASE-2026-001 \
--deadline 2026-08-01 \
--issuer "Acme Regulatory Authority" \
--timeout 10mThe program sends the notice and polls every 10 seconds until the delivery receipt arrives or the timeout expires.
- Key storage: Use
--passphrasewithkeygenand setTFEP_KEY_PASSPHRASE. The key is AES-256-GCM encrypted at rest. - Key compromise: If your signing key is compromised, immediately rotate with
./tfep-gateway rotate-key --domain authority.govand publish the new DID document. The old key can be markedrevoked: true. - Receipt forgery: Receipts are signed by the recipient's key. A forged receipt would require compromising the recipient's private key.
- Timestamp tampering: Timestamps are inside the signed envelope — any alteration breaks the signature.