Upload files to "/"

This commit is contained in:
continuist 2025-09-30 15:59:52 -04:00
parent 18089806fc
commit 9586a9d948
2 changed files with 308 additions and 0 deletions

View file

@ -0,0 +1,136 @@
# Primer: Decentralized Card & Capability Protocol
This primer introduces the main ideas of the Decentralized Card & Capability Protocol in a simplified, narrative form with examples and diagrams. It complements the full specification.
---
## 1. What is a Card?
A **Card** is a small digital envelope that carries a piece of content (a message, credential, or document). Every Card is:
- **Signed** → you know who made it
- **Optional encrypted** → you can restrict who can read it
- **Policy-bound** → it carries rules for visibility, distribution, and revocation
Think of a Card as a "post" that can be **public** or **private**, and can move around the network.
---
## 2. Capabilities
Capabilities (caps) describe *features* in the system. Each cap has a unique ID (a hash of its definition).
Examples:
- `cap:card/v1` → basic card format
- `cap:hpke-x25519-xc20p` → encryption using HPKE
- `cap:vc-staple` → attach verifiable credentials
Cards declare:
- **Requirements (`reqs`)** → features a reader MUST support
- **Provenance (`prov`)** → features the senders software actually used (optional)
### Bundles (Rollups)
Sometimes a set of caps is used together often. These can be rolled into a **bundle cap**. Expanding the bundle reveals all the atomic caps inside.
---
## 3. Anatomy of a Card
```
+-------------------------------+
| Signed Envelope (COSE_Sign1) |
|-------------------------------|
| ver, type, net, rid, ts |
| reqs, prov |
| policy_ref (hash) |
| content_uri + content_hash |
+-------------------------------+
```
- **Envelope**: signed by the creator
- **Policy capsule**: encrypted blob describing visibility & distribution
- **Content**: ciphertext payload (or plaintext for public cards)
---
## 4. Visibility Modes
- **Public**: anyone can read
- **Direct**: private to one user
- **Node**: private to members of a node
- **Trustset**: private to nodes your node trusts
- **Group**: private to a specific group of users
Recipient lists are hidden inside the encrypted policy capsule. Outsiders cant even see who the recipients are.
---
## 5. Distribution Modes
Distribution is about **where the Card is allowed to go** (not who can read it):
- `to_recipients_only` → only to recipients
- `this_node_only` → never leaves a node
- `trusted_nodes` → shared with trusted peers
- `public` → gossip freely
Distribution rules can also be encrypted so outsiders cant guess your intent.
---
## 6. Revocation
Cards that are not permanent can be **invalidated** later:
1. **Strong revoke (online gate)**
- Card points to a key gate.
- Gate can refuse further key requests → instant revoke.
2. **Crypto-shred (offline)**
- Keys are wrapped under a KEK.
- Delete the KEK → new readers cant decrypt.
⚠️ If someone already decrypted before revocation, they still have the plaintext.
---
## 7. Example Flows
### Public Post
Alice publishes a permanent public Card:
- No encryption
- Flags `permanent_public=true`
- Anyone can read forever
### Private Message
Alice sends Bob a direct Card:
- Policy capsule contains an HPKE entry for Bobs key
- Bob decrypts → gets the content
- Outsiders cant see Bob is the recipient
### Group Message
Carol posts to her study group:
- Policy capsule carries MLS group state
- Only members can open it
- Outsiders cant see whos in the group
---
## 8. Why This Matters
- **Privacy**: Audience lists are hidden
- **Control**: Users can revoke their Cards (unless marked permanent public)
- **Flexibility**: Supports nodes, trust sets, and groups without central control
- **Interoperability**: Capabilities make it possible to evolve without breaking old Cards
---
## 9. Next Steps
- Developers should first implement **public cards** + **direct cards**
- Then add **node/trustset/group encryption**
- Finally add **revocation strategies** and **bundle caps**
---
**This primer is non-normative.** For authoritative details, see the [full specification](./decentralized_cards_spec.md).

172
decentralized_cards_spec.md Normal file
View file

@ -0,0 +1,172 @@
# 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](https://www.w3.org/TR/activitypub/).
## 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 to `reqs` if omitted.
- **Bundle (rollup cap)**: A capability that implies a deterministic set of member capabilities.
- **Policy capsule**: An encrypted structure that defines the Cards 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 to `reqs`.
- `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 `reqs` for enforcement, `prov` for provenance.
- Consumers MUST reject Cards if any `reqs` are unsupported.
## 5. Visibility Modes
- **Public**: No encryption. MAY be flagged permanent.
- **Direct**: Encrypted CEK to a single recipient (HPKE).
- **Node**: CEK encrypted to a nodes group key or gate.
- **Trustset**: CEK encrypted to each trusted nodes 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 `reqs` to 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
```json
{
"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)
```json
{
"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.