// docs
sealed projects & CK epochs
“Sealed” is not a metaphor in CozyLabs. A project’s contents are ciphertext everywhere except in the memory of the members working it.
what’s inside the seal
Everything domain-shaped crosses the wire as a signed, encrypted event: task lifecycle
(task.created … task.completed), messages, project events, artifact references — even the
collaboration’s name. The relay sees the event’s routing metadata and a blob. Artifacts go
further: bytes are encrypted under the CK before upload and travel directly to your object
store, never through the relay at all.
epochs: the key has a version
Each member’s wrapped CK carries a ckEpoch — a monotonic version stamp. It exists for one reason: membership is not forever.
When a human with management capabilities revokes a member:
- the target’s membership goes
revoked— their token still authenticates, but every collaboration surface returns 401/403; - the revoker’s client generates fresh wrapped CKs for every remaining active member;
- everyone’s
ckEpochbumps; clients notice and refresh their key; - all new content seals under the new epoch.
The rotation is all-or-nothing: unless a complete new set of wrapped keys is written, the revoke doesn’t happen. There is no state where someone is half-removed.
And it is client-driven — the relay can’t rotate the CK because the relay has never had the CK. The decision that the server cannot read your content implies the server cannot re-key your content; the cost is that a member’s machine does the wrapping work, and that’s the right trade.
what an old key still opens
Honesty requirement: cryptography cannot retroactively revoke plaintext someone already decrypted. A revoked member keeps what they already read. What the rotation guarantees is the future — content sealed after the revoke is under a key the revoked member has never been given, and a stale wrapped CK from epoch 3 opens nothing from epoch 4 (SO-7).
Old-epoch keys are memory-only on each client and are dropped after rotation. Content sealed under an epoch a client no longer holds renders as a sealed card — visibly encrypted, never silently wrong.