6.6 KiB
Decentralized Card & Capability Protocol (Draft)
1. Introduction
This document specifies a decentralized protocol for the creation, distribution, and validation of signed and encrypted Cards. Cards are the fundamental unit of communication in the system. They may be public or private, and may carry access control, distribution rules, and revocation semantics. The protocol also defines a system of Capabilities that allow interoperable feature negotiation without central coordination.
This specification is written in the style of the W3C ActivityPub Recommendation.
2. Terminology
- Card: A signed object representing a unit of content. Cards may be public or private, and may be encrypted.
- Capability (cap): A content-addressed specification document that describes a feature, schema, or protocol behavior.
- Capability ID (cap_id): The multibase-encoded hash of a capability spec. Immutable.
- Requirements (
reqs): Capabilities that a verifier MUST support in order to process the Card. - Provenance (
prov): Capabilities the producer actually used when generating the Card. Defaults toreqsif omitted. - Bundle (rollup cap): A capability that implies a deterministic set of member capabilities.
- Policy capsule: An encrypted structure that defines the Card’s visibility, distribution, and keying material.
- Visibility: Who may decrypt the Card payload.
- Distribution: Where the Card may be transmitted.
- Permanent public Card: A Card with no encryption and no revocation path. Immutable.
3. Cards
3.1 Structure
A Card is a CBOR map wrapped in a COSE_Sign1 envelope. Fields:
ver: Protocol version.type: MUST be"card".net: Network identifier.rid: Unique Card identifier.ts: Creation timestamp.reqs: Array of capability IDs required to interpret the Card.prov: Optional. Array of capabilities actually used. If absent, treated as identical toreqs.policy_ref: Hash of the encrypted policy capsule.content_uri: URI of the ciphertext payload.content_hash: Integrity hash of the payload.dist_tag: Optional opaque routing hint.sig: Producer signature.
3.2 Policy Capsule
The policy capsule is an encrypted CBOR map. Fields:
visibility:"public" | "direct" | "node" | "trustset" | "group".distribution:"to_recipients_only" | "this_node_only" | "trusted_nodes" | "public".keying: HPKE encapsulations, MLS group material, or gate instructions for CEK recovery.flags: e.g.permanent_public.exp,ttl: Optional expiry or validity constraints.pad: Optional padding to obscure audience size.roster_encrypted: Optional, group roster encrypted under the group secret.
3.3 Payload
payload_ciphertext= AEAD(CEK, plaintext_card_body, AAD={net, rid, policy_ref})- Public cards MAY inline plaintext content.
4. Capabilities
4.1 Capability ID
cap_id = multibase( sha256( canonical_cbor(spec_without_signatures) ) )
4.2 Capability Spec
A capability spec is a signed document:
schema: MUST be"cap-spec/v1".name: Human-friendly name.semver: Version.purpose: Summary of semantics.behavior: Protocol rules.interop:{requires, supersedes, conflicts}.test_vectors: Golden values for conformance.docs_uri: Documentation.signatures: Array of COSE signatures from authors/curators.
4.3 Bundles
A bundle spec lists members (cap IDs). Bundles MUST expand deterministically into their atomic members before enforcement.
4.4 Negotiation
- Nodes advertise supported caps at
/.well-known/node-caps. - Cards include
reqsfor enforcement,provfor provenance. - Consumers MUST reject Cards if any
reqsare unsupported.
5. Visibility Modes
- Public: No encryption. MAY be flagged permanent.
- Direct: Encrypted CEK to a single recipient (HPKE).
- Node: CEK encrypted to a node’s group key or gate.
- Trustset: CEK encrypted to each trusted node’s group key.
- Group: CEK encrypted to an MLS group. Roster MAY remain private.
6. Distribution Modes
- to_recipients_only: Honest nodes forward only to recipients.
- this_node_only: Not gossiped beyond node.
- trusted_nodes: Forwarded only to trustset.
- public: Freely gossiped. Encryption still protects confidentiality.
Distribution policies MAY be encrypted inside the policy capsule.
7. Revocation
- Permanent public cards: Irrevocable.
- Strong revoke (online gate): CEK fetched from gate; revocation = disable at gate. Instant, requires availability.
- Crypto-shred (offline): CEK wrapped under KEK. Revocation = delete KEK. Prevents new decryption, not past.
- Card Revocation List (CRL): Optional signed log of revoked card IDs. Honest clients suppress display.
8. Security Considerations
- All hashes MUST be computed over canonical CBOR.
- Policy capsule MUST bind
{net, rid, content_hash}in AEAD AAD. - Bundles MUST be expanded before enforcement.
- Unknown required caps MUST cause rejection.
- Distribution enforcement relies on honest nodes; confidentiality relies on crypto.
- Padding SHOULD be used to obscure audience sizes.
9. Extensibility
- New caps define new features, schemas, and crypto suites.
- Specs are content-addressed, so evolution produces new cap IDs.
- Cards MAY carry adapters in
reqsto allow downgrade/interop. - Deprecated caps SHOULD publish signed deprecation notices.
10. Conformance
A conforming implementation MUST:
- Validate COSE signatures and hashes.
- Enforce all capabilities in
reqs. - Expand bundles before enforcement.
- Respect revocation policies.
- Reject unsupported or malformed Cards.
Appendix A. Example Public Card
{
"ver": 1,
"type": "card",
"net": "net:prod:z9…",
"rid": "0x12b…",
"ts": 1738123456,
"reqs": ["cap:card/v1@…"],
"body": { "schema": "card/v1", "payload_hash": "…", "content": { "msg": "hello world" } }
}
Appendix B. Example Private Card (Direct)
{
"ver": 1,
"type": "card",
"net": "net:prod:z9…",
"rid": "0x44a…",
"ts": 1738126789,
"reqs": ["cap:card/v2@…","cap:hpke-x25519-xc20p@…"],
"policy_ref": "sha256:7f…",
"content_uri": "ipfs://bafy…",
"content_hash": "sha256:aa…"
}
Status of this Document
This is a working draft. It is subject to change as the protocol evolves. Implementers SHOULD anticipate breaking changes and support migration strategies.