Files
amethyst/commons
Vitor PamplonaandClaude Opus 4.8 28b93132a3 feat(concord): read + render CORD-02 §6 encrypted community icon/banner
Concord community icons never showed (robohash instead), and the community
name silently fell back to the invite name. Root cause: the icon/banner are
CORD-02 §6 **encrypted media** — the metadata entity carries an
`ImagePointer` object `{url,key,nonce,hash}` (AES-256-GCM ciphertext at
`url`, decrypted with `key`/`nonce`, `hash` = SHA-256 of the plaintext) —
but `MetadataEntity.icon` was typed `String?`. An object where a String is
expected fails the whole entity's decode, so metadata came back null: no
icon, and the name dropped to the entry fallback. Matches the Concord v2
reference client (Armada `concord-v2/lib/{types,image}.ts`).

- Promote `ImagePointer` to a shared CORD-02 type (was invite-only) and give
  it `decryptOrNull` (AES-256-GCM via the existing `AESGCM`, verifying the
  plaintext SHA-256 — a swapped blob fails closed).
- `MetadataEntity.icon`/`banner` are now `ImagePointer?`, so the entity (and
  the community name) decodes. `ConcordChannel` carries the pointers.
- `rememberConcordImageModel` resolves a pointer for the avatar: a plain-URL
  pointer (Amethyst's own form) passes through; an encrypted one is fetched,
  decrypted, verified, cached to disk, and rendered — else the robohash. Wired
  into the Concord hub avatars and the Messages-tab community chip.
- Amethyst's create/edit still take a URL and wrap it as a url-only pointer;
  authoring encrypted images (encrypt + upload) is a follow-up.

Adds ImagePointerTest: Armada-shape object decode, decrypt round-trip, and
fail-closed on a tampered hash.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 17:16:12 -04:00
..