Cody Zoom Meetbot

Security & Technical Design

Cody Zoom Meetbot

Security & Technical Design — Cody Zoom Meetbot

Effective Date: 2026-05-15 Last Updated: 2026-05-15

Cody Zoom Meetbot ("Cody," "the App," "we," "us," or "our") is a Zoom Marketplace application operated by Obsidian Inc., d/b/a Lattice. Cody joins authorized Zoom meetings as an AI assistant to provide real-time transcription, conversational Q&A, action-item extraction, and post-meeting summaries.

This document accompanies the Cody Privacy Policy and Terms of Service. Where the Privacy Policy describes what data we collect and why, this document describes how the system is built, how that data is protected end-to-end, and what controls govern access. It is intended for Zoom Marketplace reviewers, security-conscious customers, and anyone evaluating Cody against their own information-security requirements.

This Security & Technical Design is published at https://codewarrior4life.github.io/lattice-meetbot-public/security.html and is referenced from the Cody Zoom Meetbot Marketplace listing per Zoom's Marketplace requirements.

1. Overview

This document covers the design of Cody as it pertains to the security, privacy, and integrity of user data obtained through the Zoom Marketplace OAuth grant and through the Zoom Meeting SDK. Specifically, it describes:

Where this document is silent on a control, the corresponding statement in the Privacy Policy governs. Where the two documents speak to the same control, the more restrictive of the two governs.

2. Architecture at a glance

Cody is built on a single architectural axiom: one container per meeting.

For every Zoom meeting Cody is authorized to join, the App spawns a fresh, ephemeral Linux Docker container. That container is the entire trust boundary for the meeting. It exists from the moment the meeting begins (or from the moment the host admits Cody from the waiting room) until the meeting ends or Cody is removed. When the container terminates, all in-memory state — audio buffers, decoded PCM frames, transient transcripts, chat context windows, LLM prompts — is destroyed with it. Any artifact that must outlive the meeting (the meeting WAV recording, the final transcript, the generated summary) is written to encrypted storage governed by the retention rules in §7 of this document, and the container itself is torn down.

There is no long-running multi-tenant daemon, no shared in-memory state across meetings, and no co-located processing of two meetings inside the same process. This is a deliberate failure-isolation and blast-radius decision: if a container is compromised, the only data exposed is the data for the single meeting that container was processing.

The major components inside each meeting container are:

The bot is a real meeting participant. It is not a screen-scraping browser hack. It does not animate a Chromium window or read pixels off a video frame. Audio is delivered by the SDK's audio-helper callback path as raw PCM. Video frames are not subscribed to at all, which is enforced by the SDK initialization config rather than by a downstream filter — the bytes are never delivered to the App.

3. Authentication and authorization

Cody uses a dual-credential authentication model. Two distinct credentials must be present for the bot to join a meeting, and they serve different purposes.

3.1 Meeting SDK Key/Secret → SDK JWT

The first credential is the Meeting SDK Key/Secret issued to Obsidian Inc. as the developer of Cody. At container startup, the SDK Key/Secret is loaded from the container's secret store and used to mint an HS256 JWT. The JWT is passed to SDKAuth(ctx), which authenticates the SDK client process to Zoom's signaling infrastructure.

This credential identifies the application to Zoom. It is owned by Obsidian, rotated on a periodic schedule, and is never exposed to end users, displayed in product UI, or written into logs.

3.2 End-user OAuth grant → access token, refresh token, ZAK

The second credential is the end-user OAuth grant. When a Zoom user authorizes Cody through the Marketplace, Zoom issues an OAuth access token and a refresh token scoped to the permissions the user granted (see §4). For each meeting Cody is asked to join on that user's behalf, the App exchanges those tokens for a short-lived ZAK (Zoom Access Key) token, which lets the SDK present itself in the meeting as the authorizing user's notetaker rather than as an anonymous third party.

This credential identifies the user to Zoom. Refresh tokens are stored encrypted at rest (see §6), are rotated according to Zoom's policy, and are deleted within 30 days of authorization revocation, as described in §7.

The dual-credential model means that neither the SDK Key alone nor a stolen access token alone is sufficient to join a meeting in a way that impersonates a user: the SDK Key authenticates the app, the OAuth grant + ZAK identifies the user, and both are required to produce a valid SDK join payload.

4. OAuth scopes and justifications

Cody requests the minimum set of OAuth scopes required to deliver its features. We do not request, and the App does not exercise, any *:write scope. Cody does not modify Zoom account settings, does not create or schedule meetings, does not change passwords, does not invite participants, and does not delete cloud recordings, chat history, or any other user-visible state on the Zoom side.

Scope (Zoom name) Why Cody requests it
user:read:zak Required to fetch a ZAK token so Cody can join meetings on the authorizing user's behalf. Without this scope, the bot cannot present itself as a notetaker tied to the user; without a ZAK, it cannot join.
user:read Required to identify which Zoom account authorized Cody so that we can correctly attribute artifacts (e.g., a transcript belongs to the user whose account authorized the bot) and so that we can respond to data-subject requests using verified account identifiers. We collect the user ID and the account-associated email only; no additional profile PII is read.
meeting:read:meeting Required to read meeting metadata (topic, scheduled start time, host) for the meetings Cody is asked to join. Only meetings the user explicitly points Cody at — either by passing a join URL or by scheduling through a Cody-aware orchestrator — are read. Cody does not enumerate the user's full meeting list.

Every scope is explained in plain English in the OAuth consent flow before the user accepts. If we later add a scope, that change requires both a new Marketplace review and a notification to existing authorizing users.

5. Data flows

This section walks through the seven data paths in Cody from end to end.

5.1 Authorization

The authorization flow starts in the Zoom Marketplace. The user clicks "Authorize" on the Cody listing and is redirected to Zoom's OAuth consent screen. Zoom presents the scopes from §4 above. If the user accepts, Zoom redirects back to Cody's OAuth callback endpoint with an authorization code. The callback endpoint exchanges the code for an access token and a refresh token over TLS to Zoom. Both tokens are immediately encrypted with AES-256-GCM and written to the secret store. The user's Zoom user ID and account-email are recorded against the authorization. No further information is requested or stored at this stage.

5.2 Meeting join

When the user (or an orchestrator acting for the user) requests that Cody join a meeting, the App looks up the user's encrypted refresh token, decrypts it inside the meeting-runtime service role, exchanges it for a fresh ZAK if needed, mints the SDK JWT from the Obsidian-owned SDK Key/Secret, and hands both credentials to the SDK inside a newly spawned container. The container connects to Zoom over WSS (TLS) and either joins the meeting immediately or sits in the meeting's waiting room until the host admits Cody Assistant (Notetaker).

5.3 Audio capture and transcription

Once Cody is admitted, the Meeting SDK starts delivering raw PCM audio frames via the SDK's audio-helper callback. Each frame is held briefly in an in-memory buffer inside the container. From the buffer, audio flows to two sinks:

Transcription output — text segments with timing and (where available) speaker labels — is held in memory for the duration of the meeting and serialized to the transcript artifact at meeting end. The transcript is not sent to Anthropic except when needed to answer an @cody mention or to generate the post-meeting summary; see §5.5.

5.4 Chat handling

Chat messages posted in the Zoom meeting are delivered to Cody via the SDK's chat callback. Messages addressed to Cody (those that begin with @cody or are explicitly directed to the bot's participant ID) are routed through the LLM path described below. Other messages are buffered in memory only as conversational context for the LLM and are not persisted beyond the meeting unless the user has explicitly opted in to chat retention.

5.5 Summary and reply generation

Cody calls Anthropic's Claude API for two purposes: to produce a reply when a participant addresses the bot in chat, and to generate a post-meeting summary and action-item list. In both cases, only the minimum context required is sent — typically a recent transcript window plus the chat exchange for replies, and the full transcript plus the chat log for summaries. Anthropic's commercial API terms prohibit training on customer inputs. We do not append meeting content to long-lived prompt files, vector databases, or model fine-tuning corpora.

5.6 Artifact storage

When the meeting ends or Cody is removed, the container finalizes three artifacts: the WAV recording, the transcript, and the summary/action-item document. Each is written to per-tenant encrypted storage. Each is tagged with the authorizing user's Zoom user ID, the Zoom meeting ID, and a creation timestamp. The container then terminates, and all in-memory state is destroyed.

5.7 Deletion and revocation

Users may revoke Cody's authorization from the Zoom Marketplace at any time. On revocation, Zoom invalidates the refresh token, and our token store deletes the encrypted token record within 30 days of receiving the revocation event. Users may also request artifact-level deletion at any time before the retention deadline by emailing cody@obsidian-inc.com from the email tied to their Zoom account. The default retention timer is 30 days for content artifacts (WAV, transcript, summary, chat log) and 7 days for one-off authorizations.

6. Encryption

6.1 In transit

All network traffic to and from Cody uses TLS 1.2 or higher.

We do not run user traffic through opportunistic-encryption channels or fall back to TLS 1.0/1.1 under any condition.

6.2 At rest

Sensitive data at rest is encrypted at the application layer and on the underlying storage volume.

7. Storage and retention

The retention rules below mirror Privacy Policy §6 and are reproduced here for completeness.

The more restrictive of the user's explicit instruction and the default retention window governs.

8. Access controls and tenant isolation

Each meeting container runs under its own service identity and can access only that meeting's data. There is no multi-tenant data co-mingling at the storage layer or at the runtime layer.

Production deployments enforce least-privilege IAM on the secret store: only the meeting-runtime service role may decrypt OAuth tokens, and that role is bound to a single container's lifetime. Human operators do not hold blanket decryption rights against the token store; access to production data requires a documented operational reason, and all such access is logged and auditable.

The Cody operations team's day-to-day work is performed against open-source code and against ephemeral test accounts. Production user data is touched only when an incident, a data-subject request, or a debugging need requires it.

9. Subprocessor list and justifications

The same subprocessors are listed in Privacy Policy §5; this section adds the technical rationale for each.

No additional subprocessors handle user data. We do not use third-party analytics, advertising trackers, or behavioral-targeting services anywhere in Cody.

10. Secure development lifecycle

Cody is open-source. The full source code is published at https://github.com/CodeWarrior4Life/lattice-meetbot under the Apache 2.0 license. Anyone — Zoom reviewers, customers, security researchers — can read the implementation directly rather than rely on this document alone.

Our secure development practices include:

11. Vulnerability management and disclosure

The canonical channel for vulnerability reports is GitHub Security Advisories on https://github.com/CodeWarrior4Life/lattice-meetbot. Reports can also be sent to cody@obsidian-inc.com.

Triage commitments:

We do not currently offer a paid bug bounty, but we credit reporters in advisories and release notes unless the reporter requests anonymity.

12. Incident response and breach notification

If Obsidian Inc. confirms a security incident that affects user data processed through Cody, notification will follow the timelines committed to in the Privacy Policy:

Each incident triggers a written post-incident review that captures root cause, customer impact, and follow-up controls. Post-incident reviews are shared with affected customers on request.

13. Compliance posture

Cody's compliance posture is intentionally conservative. We make the following statements honestly, including the ones that are negative.

Where a compliance regime is not listed here, customers should assume it is not in scope. We would rather be honest about our current state than overclaim and be downgraded by a reviewer for inaccuracy.

14. Open-source supply chain transparency

Cody's supply chain is intentionally legible.

Reviewers and customers who want to verify that the published image matches the published source can do so by rebuilding the image from the tagged commit.

15. Operational hardening

In addition to the controls already described, the operational posture of Cody is shaped by the principle of ephemerality.

The combination of one-container-per-meeting ephemerality, environment-scoped secrets, content-redacted logs, and opt-in optional features means that the default deployment of Cody is the most privacy-preserving deployment of Cody.

16. Reviewer contact and security questions

Zoom Marketplace reviewers, security-conscious customers, and security researchers are encouraged to reach out directly.

We will respond to security inquiries from Zoom Marketplace reviewers as a priority during the review process and within five business days otherwise.


This Security & Technical Design document is a working draft prepared for Cody Zoom Meetbot's submission to the Zoom Marketplace. It is subject to revision as the product evolves.