# dembrane documentation dembrane helps groups turn what people *say* into something they can *act on*. People speak - in a workshop, a town hall, a citizen panel, a research interview - and dembrane records, transcribes securely in dozens of languages, and turns hours of dialogue into summaries, themes, reports, and a chat you can ask questions of. We build on one belief: *people know how.* Communities already hold the knowledge to solve their own challenges. dembrane doesn't add intelligence to a group - it surfaces the intelligence already there, and keeps the humans in the room firmly in charge. dembrane was formerly called ECHO. The old name still turns up here and there, in file paths, image names, and older material. > [!NOTE] > New here? The fastest path is the *[Quick start for hosts](./users/host/getting-started.md)*. > Just here to record on someone's invitation? See *[for participants](./users/participant/index.md)*. ## Find your way in Pick the guide that matches what you're doing: - *[I run sessions and analyse them - Host](./users/host/index.md)* Create projects, collect conversations, read transcripts, chat with your data, build reports. - *[I host work for external clients - Partner](./users/host-partner/index.md)* External-client workspaces, the free observer role, data ownership and handoff. - *[I'm from dembrane - Staff](./users/staff/index.md)* Billing, account health, upgrade requests, partner ops, and trainings. - *[Someone invited me to record - Participant](./users/participant/index.md)* What to expect, how to record, and what happens to your words. - *[I build on dembrane - Developer](./users/developer-external/index.md)* Self-hosting, the API, webhooks, configuration, licensing and contributing. - *[I work on the dembrane codebase - Internal developer](./users/developer-internal/index.md)* Architecture, the data model, the processing pipeline, and how it ships. ## Browse by feature If you'd rather start from a capability than a persona, the *[feature catalogue](./features/index.md)* documents every part of dembrane on its own terms - what it is, when you'd reach for it, and who it's for. ## The whole map The *[documentation map](./map.md)* lists every page in one place. --- # Getting started as a host This guide walks you from sign-up to your first analysed conversation - about fifteen minutes of setup, plus however long people spend talking. By the end you'll have an account, a [project](./creating-a-project.md) with its [portal](./portal-editor.md) set up, a QR code to put in front of people, and at least one conversation transcribed and summarised. On the *Free* tier you get secure transcription and *one hour* of recording to try things out. Unlimited recording and the analysis features arrive on paid [tiers](../../features/tiers-and-billing.md) - you don't need them for this guide. ## 1. Sign up Go to the dashboard, create an account with your email and a password, and confirm your email. You'll be the *owner* of whatever you create, so you can do everything in it. (Turn on two-factor later in [account & security](../../features/account-and-security.md) - recommended, not required.) ## Finding your way around (and the sidebar toggle) Once signed in, you will see your main dashboard: - *The sidebar* - The sidebar on the left lets you quickly navigate between your Organisation, Workspaces, and Projects. - *Sidebar collapse* - To give yourself more screen space when reading transcripts or analysing data, you can collapse the sidebar entirely. Look for the *Sidebar Toggle* (the sidebar icon) in the sidebar header, top-right by the logo, to slide it closed. Clicking the toggle again expands it back. - *Collapse persistence* - The collapsed state persists (saved in your browser's local storage), so the sidebar stays exactly how you left it when you return or sign in again. ## 2. Create a project An onboarding wizard sets up the two containers everything lives in: a *workspace* (home for your projects, team, and billing) and your *first project* (the question or event you're collecting around). The defaults are fine - name the workspace after your team, the project after the event. Three settings are worth getting right: - *Name* - dashboard-only; participants never see it. Don't overthink it; you can rename later. - *Context* - describe the project as you would to a sincerely interested, curious friend: your goal, the sessions, the questions, anything unique. Include place names and common abbreviations. This sharpens everything downstream. - *Conversation language* - set this to what people will actually *speak*. If a Dutch conversation is set to English, it gets transcribed as English. Pick the spoken language. [Creating a project](./creating-a-project.md) has the full walkthrough. ## 3. Set up the portal The *portal* is the page people open - no account, no app - to record for you. Shape it in the [portal editor](./portal-editor.md). For a first run you only need: - A welcome *title* and *description* so people know what they're walking into, and a *finish message* for when they're done. - *Key terms* - names, jargon, and acronyms specific to your topic (without listing "dembrane" here, it gets misspelled in transcripts). Thirty seconds well spent. - Whether to *ask for a name* and/or *email*, and whether to *anonymise* transcripts. Use the *live preview* to walk it as a participant would, then move on. The fuller options - verification, Get Reply, notifications - can wait. ## 4. Share the QR or link Grab the *QR code* and *invite link* from the portal editor. Put the QR on a slide or printed sheet, or send the link in a message - anyone who scans or taps it lands straight in your portal, no sign-in. Collecting in person? The *host guide PDF* gives you a ready-to-print sheet with instructions and the code on it. > [!TIP] > Print the QR large and test it from the back of the room. One line of spoken instructions > ("scan this, allow the microphone, and just talk") loses far fewer people at the start. ## 5. Collect People open the portal, do a quick mic test, and talk - the portal handles pausing, resuming, and uploading in the background. You can mix in other ways too: record yourself in the browser if you're holding the conversation, upload transcripts you already have, or record on your phone with [dembrane Go](./using-dembrane-go-mobile.md) (currently in beta). See [collecting conversations](./collecting-conversations.md) for which to use when. ## 6. Read what comes back Conversations appear in the dashboard as soon as they start; the transcript lands about 30 seconds to a minute later (audio is sent in 30-second pieces, and high-quality transcription takes a little extra processing). Open a conversation to read the *transcript* chunk by chunk, read or regenerate the *summary*, and add *tags* to group related conversations. The [transcripts & conversations](./transcripts-and-conversations.md) guide has the full workflow. ## 7. Make sense of it Once you have a few conversations, there are two ways to dig in: - [Ask](../../features/chat-and-ask.md) - pick some conversations, start broad ("What are the main themes?"), then zoom in ("What concerns came up about X?"), then ask for the quotes. Best for comparing viewpoints and testing a hunch. - [Report](../../features/reports.md) - synthesises all conversations into a shareable document in a few minutes. Best for quickly capturing the atmosphere and main questions to send round (including people who couldn't attend). On a Changemaker workspace or above, the [library](../../features/library-and-analysis.md) also extracts topics, aspects, and quotes automatically. > [!IMPORTANT] > Built-in analysis and chat answers are tools, not verdicts. They point you at what's worth > reading - the judgement stays yours. *People know how.* ## Related - [Creating a project](./creating-a-project.md) - set up a real one properly. - [Collecting conversations](./collecting-conversations.md) - choose the right method for your session. - [Setting up the portal](./portal-editor.md) - every portal option, explained. - [Transcripts & conversations](./transcripts-and-conversations.md) - the day-to-day of working with what you've gathered. - [Roles & permissions](../../features/roles-and-permissions.md) - what you can do as owner versus member. --- # For participants Someone invited you to share your thoughts out loud, and they're using dembrane to record and make sense of what's said. These short pages explain what that's like, so you can take part with confidence. ## The promise - *No account, nothing to download.* You open a link or scan a code, and you're in. - *Quick to start.* A couple of welcome screens, a moment to agree to take part, a quick microphone check - then you talk. - *Your voice matters.* What you say is the whole point. The people in the room already hold the knowledge; your words help bring it out. - *You're in control.* Pause, stop, or - if you'd rather not speak - type instead. You choose what to share. - *Your privacy is taken seriously.* You're told what happens to your words, and you agree before anything is recorded. ## These pages - [What to expect](./what-to-expect.md) - the whole flow, from opening the link to finishing. - [Recording your conversation](./recording-your-conversation.md) - recording well, pausing, stopping, typing instead, and fixing anything that isn't working. - [Refining & verifying](./refining-and-verifying.md) - if you're asked to look back over what you said and check it was captured right. - [Your privacy & your data](./your-privacy-and-data.md) - what happens to your words, and the choices you have. - [Your report](./your-report.md) - the summary you might see at the end. > [!NOTE] > Not every step appears every time. The person who set up the session decides which parts to > include, so yours might be shorter than the list above. That's normal. > [!TIP] > If anything is unclear during a session, the person who invited you is the best one to ask - > they set it up and know what it's for. --- # For hosts You're a host if you set up a project, invite people to speak, and turn what they said into something the room can act on. Most people in the dembrane dashboard are hosts. You don't need to be technical - if you can run a meeting, you can host a dembrane project. In the [roles model](../../features/roles-and-permissions.md) a host is usually a workspace *owner*, *admin*, or *member*. Owners and admins can do everything; members can create and edit projects, read and delete conversations, chat, and build reports, but can't delete projects, invite people, or change settings. ## The journey: collect, understand, share Almost everything you do falls into three movements. *Collect.* Create a [project](./creating-a-project.md) (one per question, event, or cohort), [set up its portal](./portal-editor.md), and share a QR code or link so people can record. There are [several ways to collect](./collecting-conversations.md) - the portal, recording yourself, uploading text you already have, or recording on your phone with [dembrane Go](./using-dembrane-go-mobile.md) (currently in beta). *Understand.* Audio [transcribes automatically](../../features/transcription.md) and gets a summary. [Read and organise](./transcripts-and-conversations.md) what comes in, then [Ask questions](../../features/chat-and-ask.md) across a set of conversations and get answers with sources. On a Changemaker workspace or above, the [library](../../features/library-and-analysis.md) pulls out topics and quotes for you. *Share.* Build and publish a [report](../../features/reports.md), or [export](../../features/export-and-data-portability.md) transcripts and spreadsheets. Remember the throughline: *people know how.* Summaries and reports point you at what's worth reading - the judgement stays yours. ## Start here - [Getting started](./getting-started.md) - the fast path from sign-up to your first analysed conversation. - [Creating a project](./creating-a-project.md) - the create steps and the settings worth getting right. - [Collecting conversations](./collecting-conversations.md) - every way to gather input. - [Setting up the portal](./portal-editor.md) - configuring the page participants see. - [Transcripts & conversations](./transcripts-and-conversations.md) - reading and tidying what you've collected. - [Using dembrane Go on mobile](./using-dembrane-go-mobile.md) - recording from your phone (beta). - [Getting help](./getting-help.md) - every way to reach the dembrane team when you're stuck. ## Related - [Feature catalogue](../../features/index.md) - the canonical reference your guides link back to. - [Roles & permissions](../../features/roles-and-permissions.md) - what each role can do. - [Tiers & billing](../../features/tiers-and-billing.md) - what each plan includes. - [The partner guides](../host-partner/index.md) - where *external* and *observer* collaborators fit. --- # Partner overview You're a partner when dembrane has flagged your organisation as one - a trusted agency, consultancy or research outfit that runs dembrane *on behalf of other people*. You can do everything an ordinary [host](../host/index.md) can; partner status just adds a few abilities for running work that belongs to a client rather than to you. The one to know is the *external-client workspace*: it bills on its own, names a *data owner* (the client), and quietly invites that client in as a free, read-only [observer](./observer-and-external-collaborators.md) so they can always watch their own data being handled. Reach for partner features when the work isn't really yours - you're holding conversations, transcripts and reports for someone else, and the data is theirs. A research agency running citizen panels a municipality owns; a consultancy facilitating staff sessions it bills the hospital for and will hand over at the end; a client who should *see* findings without paying for a seat. If you're running sessions for your *own* organisation, none of this applies - the [host guides](../host/index.md) are all you need. To use any of it you must be a workspace *owner* or *admin* inside a partner organisation. The partner flag itself is set by dembrane staff - see [becoming a partner](./becoming-a-partner.md). > [!NOTE] > Partner status doesn't change what your *team* can do. It changes what kinds of *workspaces* > you can create and how they're billed and owned. Colleagues still work through their ordinary > [roles](../../features/roles-and-permissions.md). ## In this section - [Becoming a partner](./becoming-a-partner.md) - how an org is made a partner, what it unlocks, and the partner agreement. - [External-client workspaces](./external-client-workspaces.md) - creating a workspace that belongs to a client: the data-owner step, separate billing, the auto-invited observer, whitelabel. - [Observer & external collaborators](./observer-and-external-collaborators.md) - the free read-only *observer* versus the paid *external* collaborator, and when to use each. - [Data ownership & handoff](./data-ownership-and-handoff.md) - naming a data owner, moving projects and workspaces, and handing a workspace over. - [Referrals](./referrals.md) - the referral ledger, and the kickbacks and discounts dembrane staff administer. ## Related - [The partner program](../../features/partner-program.md) - the role-neutral reference for partner orgs and external-client workspaces. - [Data ownership & compliance](../../features/data-ownership-and-compliance.md) - internal versus external workspaces, who owns what, the GDPR posture. - [Roles & permissions](../../features/roles-and-permissions.md) - observer, external, and the rest. - [Host overview](../host/index.md) - everything a partner can also do. --- # For staff These pages cover the *admin panel*: the staff-only console behind the dashboard that lets you do things no customer can - chase renewals, approve upgrades, issue invoices, grant trials, run trainings. They're for dembrane employees with an admin account. Customer roles (owner, admin, member, billing, external, observer) live *inside* an organisation or workspace. Staff sit outside that [model](../../features/roles-and-permissions.md): you operate across every account, see all workspaces and invoices, and hold the controls to change them. A staff member can also be a host running their own projects - the panel is just a separate, separately gated surface. ## Getting in The admin panel is a separate, staff-only area, gated apart from the normal dashboard. You reach it with a dembrane staff account. If you can't see it, your account isn't set up as staff yet - ask whoever manages staff access. A few of the most sensitive actions - changing a workspace's tier or visibility, or transferring it to a new owner - need extra permission on top of staff access. If one of those is greyed out for you, you don't have it yet; everything else on this page you can do. ## What you can do here - *[The admin panel](./admin-panel-overview.md)* - how to reach it, how it's laid out (Usage & billing, At-risk, Payments, Training), and the kebab-action model that runs through it. - *[Usage & billing rollup](./usage-and-billing-rollup.md)* - every account: usage per account and workspace, revenue class (trial / managed / comped / paying), MRR forecast, admin contacts, CSV export, 12-month lookback, filters. - *[Account health & at-risk](./at-risk-and-account-health.md)* - accounts that need a human: pilot hard-blocks, at-cap, approaching-cap, recent downgrades, and the outreach for each. - *[Upgrade requests](./upgrade-requests.md)* - approve or deny new-workspace and tier-upgrade requests; how notifications and the daily digest batch. - *[Managed & offline billing](./managed-and-offline-billing.md)* - set an account managed, assign an account manager, issue a payment link or invoice (VAT / e-invoice), mark paid. - *[Discounts, trials & tiers](./discounts-trials-and-tiers.md)* - apply a discount, grant a reverse trial, change a tier, change the admin, reset usage. - *[Partner administration](./partner-administration.md)* - the partner toggle, referral ledger, external-led-orgs signal, and workspace handoff. - *[Trainings & licences](./trainings-and-licences.md)* - run the catalogue: schedule sessions, complete them to grant one-year licences, manage the roster. - *[Staff support access](../../features/staff-support-access.md)* - how to join customer workspaces temporarily for support, extend sessions, or request access when support access is toggled off. ## The customer side, for reference Most actions here affect what customers experience on the dashboard: - [Tiers & billing](../../features/tiers-and-billing.md) - the plans you change, plus seats and billing accounts. - [Roles & permissions](../../features/roles-and-permissions.md) - the customer roles you read in the rollup. - [The partner program](../../features/partner-program.md) - what the partner toggle unlocks. - [Trainings](../../features/trainings.md) - the customer-facing view of the licences you grant. ## Related - [Staff support access](../../features/staff-support-access.md) - join or request access to a customer workspace. - [The admin panel](./admin-panel-overview.md) - how the panel is laid out and reached. - [Usage & billing rollup](./usage-and-billing-rollup.md) - the master table you start from. - [Feature pages](../../features/index.md) - what a customer sees, when you need to check. --- # Building on dembrane dembrane is open source. If you want to run it on your own infrastructure, point your own language-model keys at it, integrate it with your systems, or contribute code, these pages are for you. dembrane captures, transcribes, and makes sense of spoken conversations at scale. The same platform that powers the managed service at dembrane.com is the code you can clone, read, and run yourself. Our core belief - *PEOPLE KNOW HOW* - applies to the codebase too: the knowledge is in the room, and we'd rather surface it than gate it. ## What's open source The dembrane repository (the "echo" codebase: dashboard, participant portal, FastAPI backend, agent service, and Directus configuration) is published under the *Business Source License 1.1 (BSL 1.1)*. In short: - *Non-production use is unrestricted* - read it, run it locally, fork it, learn from it. - *Production use is free* if your organisation's total finances are *at or below €1,000,000 over any rolling twelve-month period*. - Each release's *Change Date* is its release date plus three years, after which that release converts to *GPLv3*. If you're above the threshold and want to run dembrane in production, there's a commercial licence. The full terms, the threshold, and who to contact are on the [licensing](./licensing.md) page - read it before you deploy. > [!NOTE] > dembrane was formerly called ECHO, so the old name still shows up in the repository name, > container images, and Kubernetes namespaces. These guides say "dembrane", "the dashboard", > and "the portal". ## The three ways to run dembrane 1. *Managed SaaS* - dembrane.com hosts everything: the host dashboard at `dashboard.dembrane.com` and the participant portal at `portal.dembrane.com`. You bring nothing but a browser. This is the right choice for most teams; see [tiers & billing](../../features/tiers-and-billing.md). 2. *Open source, self-hosted* - you run the services yourself, on your own infrastructure, with your own database, object storage, and language-model providers. Start with [self-hosting](./self-hosting.md). 3. *Self-hosted with your own data location and providers* - the same as above, tuned for data residency (for example, EU-only regions and providers). See the EU residency notes in [self-hosting](./self-hosting.md) and [configuration & LLM providers](./configuration-and-llm-providers.md). The managed service and the open-source code are the same product. Tier gating (for example, which features need a Changemaker workspace) is a billing concept on the managed service; when you self-host you operate the whole platform. ## The pages here *Run it yourself* - *[Self-hosting](./self-hosting.md)* - the services dembrane needs, the dev container, ports, environment files, and EU-residency options. - *[Configuration & LLM providers](./configuration-and-llm-providers.md)* - wiring up language models with the LiteLLM router, transcription and embedding providers, EU regions, and feature toggles. - *[Authentication](./authentication.md)* - how dembrane authenticates requests: Directus JWTs, static integration tokens, and the staff `admin_access` claim. *Integrate with it* - *[The participant API](./participant-api.md)* - the unauthenticated endpoints the portal uses to record conversations; the typical upload sequence. - *[Webhooks](./webhooks.md)* - react to `conversation.*` and `report.generated` events in your own systems, with signature verification. - *[Export & integrations](./export-and-integrations.md)* - pulling transcripts, reports, and CSV/Excel out of dembrane programmatically. - *[MCP & bring-your-own-LLM](./mcp-and-byo-llm.md)* - the forthcoming way to connect your own assistant (ChatGPT, Claude) to your dembrane data. *Contribute & licence* - *[Licensing](./licensing.md)* - BSL 1.1 in full, the Change Date, and the commercial licence. - *[Contributing](./contributing.md)* - how to send a pull request, the CLA, the code of conduct, and how to disclose a security issue. ## How it fits together (the short version) Self-hosting means running a handful of services that talk to each other: - a *FastAPI backend* on port `8000` (the `/api/*` and `/api/v2/*` routes); - an *agent service* on port `8001` (agentic chat); - *Directus* on port `8055` (the data, auth, and file layer); - background *workers* and a *scheduler* (transcription, summaries, reports); - the web frontend, serving the *dashboard* on `5173` and the *participant portal* on `5174`; - and the infrastructure they depend on: *PostgreSQL with pgvector*, *Redis/Valkey*, and *S3-compatible object storage* (MinIO, DigitalOcean Spaces, AWS S3, …). If you want the deep, code-level reference for any of these, the [internal developer guides](../developer-internal/index.md) - for example [architecture](../developer-internal/architecture.md) and the [processing pipeline](../developer-internal/processing-pipeline.md) - go further than these external guides do. ## Related - [Self-hosting](./self-hosting.md) - [Internal developer overview](../developer-internal/index.md) - [Tiers & billing](../../features/tiers-and-billing.md) - [Feature catalogue](../../features/index.md) --- # Internal developer overview These pages are for engineers working *on* the dembrane codebase - not self-hosters or API integrators (those are the [external developer guides](../developer-external/index.md)). The goal here is to get you oriented fast: where each service lives, how the data flows, and how a change reaches production. > [!NOTE] > This is internal reference. It assumes you have the `echo` monorepo checked out and access > to the team's tooling. If you're self-hosting or building against the public API, start with > [self-hosting](../developer-external/self-hosting.md) and > [the participant API](../developer-external/participant-api.md) instead. ## What dembrane is, in one paragraph People speak - in a workshop, a town hall, a citizen panel, a research interview - and dembrane records, transcribes securely in dozens of languages, and turns hours of dialogue into summaries, themes, reports, and a chat you can interrogate. The platform is event-driven: audio arrives in chunks, work fans out to background workers, and the dashboard streams progress back over SSE. We treat language models as tools, not oracles - the human stays in the room and in charge. ## The repo at a glance Everything lives in one monorepo, `echo/`. The pieces you'll touch most: | Path | What it is | |---|---| | `echo/server/` | The FastAPI backend, Dramatiq workers, and the APScheduler. The heart of the system. | | `echo/server/dembrane/` | The Python package: API routers, service layer, tasks, settings, policies. | | `echo/frontend/` | The React/TypeScript SPA. One codebase serves both the *dashboard* and the *participant portal* - it picks the router by hostname. | | `echo/agent/` | The standalone agent service (CopilotKit + LangGraph) for agentic chat. Runs on its own port. | | `echo/directus/` | The Directus deployment: data layer, auth, file storage, and the schema snapshot (`sync/snapshot/`). | | `echo/docs/` | Engineering docs - ADRs, plans, issues, migration notes, the LiteLLM config reference. | | `dembrane-go/` | The native SwiftUI iOS recording app. Separate build; talks to the same backend. | | `echo/tools/` | Operational tooling (e.g. usage tracker). | ## The services dembrane is several processes, not one. Each guide below goes deeper, but the shape is: - *FastAPI backend* on `:8000` - the v1 (`/api/*`) and v2 (`/api/v2/*`) APIs, the BFF layer, and the service layer. - *Agent service* on `:8001` - agentic chat, leased turns in Redis. - *Directus* on `:8055` - the data and auth layer. - *Dramatiq workers* - a `network` queue (gevent, for async I/O) and a `cpu` queue. - *APScheduler* - a blocking scheduler that fans periodic work out to Dramatiq. - Backing stores: *PostgreSQL* (with pgvector), *Redis/Valkey*, *S3* (MinIO or DigitalOcean Spaces). See [architecture](./architecture.md) for the full picture, including ports, the BFF, and auth. ## Where to read next Start with [architecture](./architecture.md), then dip into whichever area you're working on: - *[Architecture](./architecture.md)* - services, ports, the v1/v2 split, the BFF and service layers, and how authentication works (Directus JWT, the `admin_access` claim). - *[The data model](./data-model.md)* - the 49 Directus collections and how org → workspace → project → conversation hang together. - *[The processing pipeline](./processing-pipeline.md)* - what happens between an uploaded chunk and a finished summary; transcription, correction, merge, summarise, reports. - *[Chat & the agent service](./chat-and-agent.md)* - standard RAG chat versus agentic chat, the LangGraph tools, and the lease-based runtime. - *[Roles & policies in code](./roles-and-policies.md)* - `policies.py`, seats, inheritance, and how to add a capability or a role arm. - *[Background jobs & scheduler](./background-jobs-and-scheduler.md)* - Dramatiq queues, the no-asyncio-in-actors rule, and every scheduled job. - *[Local development](./local-development.md)* - the devcontainer, `mprocs`, env files, and running everything on your machine. - *[Deployment & releases](./deployment-and-releases.md)* - how `main` and tags ship, the GitOps repo, and database migrations. - *[Developing & maintaining the docs](./maintaining-docs.md)* - the two-way docs/code sync, the code-to-docs process, and the review gate. ## Two files you should read before you change anything - `echo/AGENTS.md` (and the per-area `echo/server/AGENTS.md`, etc.) - the cross-cutting rules that aren't obvious from one read of a file: the Dramatiq/gevent gotchas, the two independent email senders, the settings pattern, brand and UI copy rules. Read it first; fix stale paths when you spot them. - `echo/docs/adr/` - the architecture decision records. These explain *why* the system looks the way it does. The ones you'll meet most: - [ADR 0001](./background-jobs-and-scheduler.md) - over-cap conversation model (Free-tier hour limit). - ADR 0002 - billing-period toggle (monthly premium). - ADR 0003 - external as a stored role (see [roles & policies](./roles-and-policies.md)). - ADR 0004 - unified invite modal and org-only membership. - ADR 0005 - the per-seat tier overhaul (supersedes parts of 0001/0002). ## House conventions worth knowing early - *Config goes through `settings.py`.* Add env vars as fields on `AppSettings`; fetch with `settings = get_settings()`. Never read `os.environ` directly. (`echo/server/AGENTS.md`.) - *Prefer Directus queries over raw SQLAlchemy* in API handlers reading project/conversation data - it keeps behaviour aligned with the admin console. - *No asyncio inside Dramatiq actors.* The `network` workers run under gevent; use `run_async_in_new_loop` / `run_in_thread_pool`. See [background jobs](./background-jobs-and-scheduler.md). - *Local entry points go through `uv run` so env and deps stay consistent. --- # Feature catalogue This is the canonical reference for what dembrane *does*. Each page explains a single capability: what it is, the moment you'd reach for it, which role and tier it's for, and how it works. If you'd rather read from your own point of view, start with *[who you are](../users/index.md)* instead - those guides link back here. ## Foundations How dembrane is organised, who can do what, and what each plan unlocks. - *[Organisations & workspaces](./organisations-and-workspaces.md)* - the containers your projects and people live in. - *[Roles & permissions](./roles-and-permissions.md)* - owner, admin, member, billing, external, observer, and what each can do. - *[Tiers & billing](./tiers-and-billing.md)* - Free, Innovator, Changemaker, Guardian, per-seat pricing, and what's gated where. - *[Invites & access](./invites-and-access.md)* - adding people by email or link, and how access requests work. - *[Visibility & discovery](./visibility-and-discovery.md)* - open, invite-only, or private workspaces. - *[Account & security](./account-and-security.md)* - your profile, password, two-factor, and audit logs. - *[Staff support access](./staff-support-access.md)* - how dembrane administrators access your workspace to help troubleshoot. ## Collecting conversations Getting spoken (or written) input into dembrane. - *[Projects](./projects.md)* - where a body of conversations and its analysis lives. - *[Recording](./recording.md)* - capturing audio, in the browser or on mobile. - *[Transcription](./transcription.md)* - turning audio into accurate, multilingual text. - *[The live monitor](./live-monitor.md)* - watch participant flow, mic checks, and recording in real time. - *[The participant portal](./portal-and-participant-experience.md)* - the no-account experience people use to record for you. - *[The portal editor](./portal-editor.md)* - how you shape that experience. - *[dembrane Go (mobile)](./mobile-app-dembrane-go.md)* - the native iOS recorder, currently in beta. ## Making sense of it Turning hours of dialogue into understanding. - *[Conversations & transcripts](./conversations-and-transcripts.md)* - reading, editing, tagging, and organising what you've collected. - *[Chat & Ask](./chat-and-ask.md)* - ask questions across your conversations and get cited answers. - *[Library & analysis](./library-and-analysis.md)* - automatically extracted topics, aspects, and quotes. - *[Reports](./reports.md)* - assemble and share findings. ## Working with others - *[The partner program](./partner-program.md)* - hosting work for external clients. - *[Data ownership & compliance](./data-ownership-and-compliance.md)* - who owns the data, internal vs external workspaces, GDPR posture. - *[Trainings](./trainings.md)* - getting your team certified for high-stakes settings. - *[Notifications](./notifications.md)* - how dembrane keeps you informed. ## Getting data out & building on dembrane - *[Export & data portability](./export-and-data-portability.md)* - transcripts, reports, CSV/Excel. - *[Webhooks & integrations](./webhooks-and-integrations.md)* - react to events in your own systems. - *[MCP & bring-your-own-LLM](./mcp-and-bring-your-own-llm.md)* - connect your own model or assistant. --- # Documentation map Everything in one place. Two ways through it: by *feature* (the canonical reference for each capability) or by *who you are* (the same capabilities, told from your vantage - when you'd use them, and as which role). ## By feature The canonical reference. Each page explains what a capability is, when you'd use it, who it's for, and how it works. - [Feature catalogue](./features/index.md) - [5 ways to use dembrane](./features/five-ways-to-use-dembrane.md) - [Roles & permissions](./features/roles-and-permissions.md) - [Tiers & billing](./features/tiers-and-billing.md) - [Organisations & workspaces](./features/organisations-and-workspaces.md) - [Projects](./features/projects.md) - [Recording](./features/recording.md) - [Live monitor](./features/live-monitor.md) - [Transcription](./features/transcription.md) - [Conversations & transcripts](./features/conversations-and-transcripts.md) - [Chat & Ask](./features/chat-and-ask.md) - [Library & analysis](./features/library-and-analysis.md) - [Reports](./features/reports.md) - [The participant portal](./features/portal-and-participant-experience.md) - [The portal editor](./features/portal-editor.md) - [Invites & access](./features/invites-and-access.md) - [Staff support access](./features/staff-support-access.md) - [Visibility & discovery](./features/visibility-and-discovery.md) - [Data ownership & compliance](./features/data-ownership-and-compliance.md) - [The partner program](./features/partner-program.md) - [Trainings](./features/trainings.md) - [Webhooks & integrations](./features/webhooks-and-integrations.md) - [Export & data portability](./features/export-and-data-portability.md) - [MCP & bring-your-own-LLM](./features/mcp-and-bring-your-own-llm.md) - [dembrane next (preview features)](./features/dembrane-next.md) - [Building now (user stories for upcoming features)](./building/index.md) - [Account & security](./features/account-and-security.md) - [Notifications](./features/notifications.md) - [dembrane Go (the mobile app)](./features/mobile-app-dembrane-go.md) ## By who you are [All user types →](./users/index.md) ### Host - running and analysing sessions - [Host overview](./users/host/index.md) - [Getting started](./users/host/getting-started.md) - [Creating a project](./users/host/creating-a-project.md) - [Collecting conversations](./users/host/collecting-conversations.md) - [Setting up the portal](./users/host/portal-editor.md) - [Transcripts & conversations](./users/host/transcripts-and-conversations.md) - [Troubleshooting transcripts & summaries](./users/host/troubleshooting-transcripts-and-summaries.md) - [Chat & Ask](./users/host/chat-and-ask.md) - [Library & analysis](./users/host/library-and-analysis.md) - [Reports](./users/host/reports.md) - [Managing your workspace](./users/host/managing-your-workspace.md) - [Tiers, billing & usage](./users/host/tiers-billing-and-usage.md) - [Account & settings](./users/host/account-and-settings.md) - [Using dembrane Go on mobile](./users/host/using-dembrane-go-mobile.md) ### Host - partner features - [Partner overview](./users/host-partner/index.md) - [Becoming a partner](./users/host-partner/becoming-a-partner.md) - [External-client workspaces](./users/host-partner/external-client-workspaces.md) - [Observer & external collaborators](./users/host-partner/observer-and-external-collaborators.md) - [Data ownership & handoff](./users/host-partner/data-ownership-and-handoff.md) - [Referrals](./users/host-partner/referrals.md) ### Staff - dembrane internal operations - [Staff overview](./users/staff/index.md) - [Staff support access](./features/staff-support-access.md) - [The admin panel](./users/staff/admin-panel-overview.md) - [Usage & billing rollup](./users/staff/usage-and-billing-rollup.md) - [Account health & at-risk](./users/staff/at-risk-and-account-health.md) - [Upgrade requests](./users/staff/upgrade-requests.md) - [Managed & offline billing](./users/staff/managed-and-offline-billing.md) - [Discounts, trials & tiers](./users/staff/discounts-trials-and-tiers.md) - [Partner administration](./users/staff/partner-administration.md) - [Trainings & licences](./users/staff/trainings-and-licences.md) ### Participant - recording on an invitation - [Participant overview](./users/participant/index.md) - [What to expect](./users/participant/what-to-expect.md) - [Recording your conversation](./users/participant/recording-your-conversation.md) - [Refining & verifying](./users/participant/refining-and-verifying.md) - [Your privacy & your data](./users/participant/your-privacy-and-data.md) - [Your report](./users/participant/your-report.md) ### Developer - building on dembrane (external) - [External developer overview](./users/developer-external/index.md) - [Self-hosting](./users/developer-external/self-hosting.md) - [Configuration & LLM providers](./users/developer-external/configuration-and-llm-providers.md) - [Authentication](./users/developer-external/authentication.md) - [The participant API](./users/developer-external/participant-api.md) - [Webhooks](./users/developer-external/webhooks.md) - [Export & integrations](./users/developer-external/export-and-integrations.md) - [MCP & bring-your-own-LLM](./users/developer-external/mcp-and-byo-llm.md) - [Licensing](./users/developer-external/licensing.md) - [Contributing](./users/developer-external/contributing.md) ### Developer - working on the codebase (internal) - [Internal developer overview](./users/developer-internal/index.md) - [Architecture](./users/developer-internal/architecture.md) - [The data model](./users/developer-internal/data-model.md) - [The processing pipeline](./users/developer-internal/processing-pipeline.md) - [Chat & the agent service](./users/developer-internal/chat-and-agent.md) - [Roles & policies in code](./users/developer-internal/roles-and-policies.md) - [Background jobs & scheduler](./users/developer-internal/background-jobs-and-scheduler.md) - [Local development](./users/developer-internal/local-development.md) - [Deployment & releases](./users/developer-internal/deployment-and-releases.md) - [Developing & maintaining the docs](./users/developer-internal/maintaining-docs.md) --- # Creating a project A *project* is where one body of conversations and its analysis lives - the [conversations](./transcripts-and-conversations.md) you collect, the [portal](./portal-editor.md) people record through, and the [chat](../../features/chat-and-ask.md), [library](../../features/library-and-analysis.md), and [reports](../../features/reports.md) built from them. Make one per question or event: "Spring budget consultation," "Q3 user interviews," "Team retro - June." If you want two very different summaries out of one project, that's a sign it should be two. You need to be a workspace *owner*, *admin*, or *member* to create a project. (A *workspace* is the container for your people, billing, and projects; a project lives inside it. One workspace, many projects - more in [organisations & workspaces](../../features/organisations-and-workspaces.md).) ## The create steps The wizard is three short steps: 1. *Name & context* - give it a clear name and a paragraph of context (see the tips below). 2. *Access* - *open to your workspace* (the default; everyone in the workspace can find it) or *private* (restricted even within the workspace). Private needs an *Innovator* workspace or above; on [Free](../../features/tiers-and-billing.md), projects are open. 3. *Review* - confirm and create. You land on the project home, ready to [set up the portal](./portal-editor.md) and start collecting. ## The settings that matter You can change all of these later under *settings → overview*. *Name* is dashboard-only - participants never see it, so name it for your own clarity. *Context* is where the work pays off. Describe the project as you would to a sincerely interested, curious friend: your goal, the sessions, the questions you're chasing, anything unique about it. Include place names, locations, and common abbreviations. The richer the context, the better the summaries and reports. *Language* must match what people will actually *speak*. > [!IMPORTANT] > If a Dutch conversation is set to English, it gets transcribed as English. Pick the spoken > language. [Transcription](../../features/transcription.md) is multilingual and handles > code-switching, but the primary language has to be right. *Participant name* is what dembrane calls the people who record - "participant," "resident," "student," "member." It shows in the [portal](./portal-editor.md) and your conversation lists, so pick the word your audience recognises. *Conversation toggle* controls whether new conversations can be added - use it to close a project to new input once a session is over, while keeping everything readable. You can also *move* the project to another workspace (handy if you created it in the wrong place) and *delete* it. > [!WARNING] > Deleting a project is permanent and takes its conversations with it. If you only want to > stop new input, use the conversation toggle instead. ## A sensible first setup 1. Name it after the event, add a rich paragraph of context. 2. Leave it *open to your workspace*. 3. Set *language* to your room's spoken language. 4. Set *participant name* to whatever your audience calls themselves. 5. Head to the [portal editor](./portal-editor.md) for title, description, finish message, and key terms. 6. Share the [QR or link](./collecting-conversations.md). ## Related - [Projects](../../features/projects.md) - the canonical feature reference. - [Setting up the portal](./portal-editor.md) - configure what participants see. - [Collecting conversations](./collecting-conversations.md) - every way to gather input. - [Organisations & workspaces](../../features/organisations-and-workspaces.md) - the containers above projects. - [Tiers & billing](../../features/tiers-and-billing.md) - what's gated where. --- # Setting up the portal The *portal* is the page participants open - no account, no app - to record for you. You shape it in the *portal editor*, under the project's *settings → portal editor* (open to workspace *owners*, *admins*, and *members*). Set it up once when a project starts, dip back in to adjust wording, and a few minutes here pays off in cleaner recordings and fewer confused participants. For the role-neutral reference, see [the portal editor](../../features/portal-editor.md). ## Wording: title, description, finish text The three pieces every participant reads: - *Title* - the welcome heading, in plain words ("Tell us about your street"). - *Description* - a sentence or two on what you're asking and why, and roughly how long. - *Finish text* - the thank-you shown when someone's done, plus anything they should know about what happens next. ## Key terms (the highest-value field) *Key terms* are the proper nouns, jargon, place names, and acronyms specific to your topic - the words a general transcriber would mangle. List them and [transcription](../../features/transcription.md) gets them right far more often. > [!TIP] > Add neighbourhoods, products, people, schemes, and any abbreviation you'll hear > repeatedly. (Without "dembrane" listed here, even that gets misspelled.) Thirty seconds > saves a lot of correcting later. ## What you ask of participants - *Ask for name* - attaches a name to each conversation so you can tell them apart. - *Ask for email* - lets you follow up or send a report. Turn both off for a fully anonymous drop-in; turn them on when you need to attribute or follow up. Be guided by what you actually need - see [data ownership & compliance](../../features/data-ownership-and-compliance.md). *Anonymise transcripts* redacts personal information during processing. Use it for sensitive topics or when you've promised anonymity - it pairs well with leaving name and email off. *AI title & tags* generates a title and tags for each conversation automatically, so your list is readable without manual labelling. Leave it on unless you want to title everything yourself. ## Portal language The portal language only changes the *intro screens* a participant reads - the welcome and instructions. It does *not* change the language of transcripts: those stay in the language people actually speak, which you set on the [project](./creating-a-project.md). ## Notifications and email Participants can leave an *email* at the end to be notified when reports are ready or updated - great for post-event follow-up, and it pairs with auto-sending a [report](../../features/reports.md). You can also subscribe to be [notified](../../features/notifications.md) about portal activity, so you know when conversations are coming in without watching the dashboard. ## The optional extras You can ignore these for a first run: - *Get Reply* - gives participants a spoken reply after they record, shaped by a prompt you set. Use it when you want the portal to feel like a two-way exchange. Set the mode and prompt here. - *Verification* - asks participants to confirm what was understood before they finish; they review extracted points and approve, reject, or modify them. Enable it, run it *on finish*, and set *topics* (predefined or custom). Worth it for high-stakes input; skip it for a quick drop-in. The participant-side flow is in [the participant portal](../../features/portal-and-participant-experience.md). - *Portal tags* - tags attached to every conversation collected through this portal, so you can filter and group them later in [conversations](./transcripts-and-conversations.md). ## Preview, then share Use the *live preview* to walk the portal as a participant would: read the title and description aloud, check the finish text, and confirm the name/email questions match what you intend. Fix the wording until it reads cleanly to someone who knows nothing about your project. Then grab the *QR code* and *invite link* and you're into [collecting conversations](./collecting-conversations.md). ## Leaving fields empty: the defaults An empty field is not broken - it means the built-in default applies. When you ask about your settings in [Ask](./chat-and-ask.md), unset fields read as *default*. What each default does: - *Title* and *description* empty - participants see only the built-in recording instructions, with no custom heading or intro above them. - *Finish text* empty - the built-in thank-you screen, unchanged. - *Key terms* empty - transcription runs on general vocabulary only, so your topic's names and jargon are more likely to be misspelled. - *Reply prompt* empty - replies follow the built-in behaviour for the selected reply mode. Fill a field to override its default; clear it to go back. ## A good default portal - Clear *title*, one-line *description*, warm *finish text*. - A solid list of *key terms*. - *Ask for name* on, email off (on only if you'll follow up). - *Anonymise* on for sensitive topics. - *AI title & tags* on. - *Verification* off unless accuracy sign-off matters. - Preview, then share the *QR*. ## Related - [The portal editor](../../features/portal-editor.md) - canonical feature reference. - [The participant portal](../../features/portal-and-participant-experience.md) - what participants experience. - [Collecting conversations](./collecting-conversations.md) - sharing the QR and other methods. - [Transcription](../../features/transcription.md) - why key terms matter. - [Data ownership & compliance](../../features/data-ownership-and-compliance.md) - handling names, emails, and anonymisation responsibly. --- # Tiers & billing A *tier* is the plan a workspace is on - it decides which features that workspace has. There are four, and they stack: each one includes everything below it. Plans are counted in seats. Contact dembrane for current pricing - see [what it costs](#what-it-costs). ## What each plan gives you | Capability | Free | Innovator | Changemaker | Guardian | |---|---|---|---|---| | Secure [transcription](./transcription.md) | ✓ | ✓ | ✓ | ✓ | | Recording hours | 1 h | unlimited | unlimited | unlimited | | Bring your own language model + [MCP](./mcp-and-bring-your-own-llm.md) | – | ✓ | ✓ | ✓ | | Built-in analysis ([library](./library-and-analysis.md), summaries, themes) | – | – | ✓ | ✓ | | [Audit logs](./account-and-security.md#audit-logs) | – | – | ✓ | ✓ | | [White labelling](./data-ownership-and-compliance.md) | – | – | ✓ | ✓ | | EU-sovereign stack | – | – | – | ✓ | What each one is for: - *Free* - one hour of recording, a single user, open registration, and the same secure, multilingual transcription as every paid tier. It's the only tier with an hour cap. On Free the heavier features ([chat](./chat-and-ask.md), [reports](./reports.md), extra workspaces) are gated, and you'll be prompted to upgrade when you reach for them. - *Innovator* - unlimited hours, plus the option to point your own ChatGPT or Claude at your conversations over [MCP](./mcp-and-bring-your-own-llm.md) instead of dembrane's built-in analysis. *Coming soon*, once the MCP integration ships. - *Changemaker* - adds dembrane's [built-in analysis](./library-and-analysis.md) on EU-hosted language models, [audit logs](./account-and-security.md#audit-logs), and [white labelling](./data-ownership-and-compliance.md). - *Guardian* - everything in Changemaker on an EU-sovereign, CLOUD-Act-safe stack for the strictest compliance needs. *Coming soon*. > [!TIP] > Need bespoke compliance terms or to run dembrane yourself? Those go beyond the standard > tiers - see [data ownership & compliance](./data-ownership-and-compliance.md) and the > [external developer guides](../users/developer-external/index.md). ## What it costs When you reach something that isn't on your plan, dembrane opens a short set of questions about what you need and lets you pick a time to talk it through. You can also write to info@dembrane.com. ## What a seat is A *seat* is what a person occupies in a workspace. Most roles use one - owner, admin, member, billing, and external. The [observer](./roles-and-permissions.md#the-free-read-only-observer) role is free and never does. Two things make seats easy to live with: - *They're metered, never blocked.* You can always add someone - dembrane counts the seat and reflects it in your bill rather than stopping the invite. Pending invites count too; observer invites don't. See [invites & access](./invites-and-access.md#seats-and-pending-invites). - *A person counts once per workspace.* Seats are pooled across the workspaces in a billing account, and the same person in the same workspace is a single seat, not one per project. > [!TIP] > The mental model is "add who you need, watch the count." If someone only needs to *see* > results, make them a free > [observer](./roles-and-permissions.md#the-free-read-only-observer). ## How billing is organised Billing attaches to a *billing account*, scoped one of two ways: - *Pooled across your organisation* - the default. All your [internal workspaces](./organisations-and-workspaces.md) share one account and pool their seats. - *Per workspace* - used for external-client workspaces, where a [partner](./partner-program.md) runs work for someone else. That workspace gets its own account so the client's usage stays cleanly apart. The full split, and what it means for data ownership, is in [data ownership & compliance](./data-ownership-and-compliance.md). Payments go through Mollie for workspaces that already hold a subscription. Where dembrane needs to invoice offline - larger or public-sector customers paying by bank transfer - staff can arrange managed invoicing ([staff billing guides](../users/staff/managed-and-offline-billing.md)). > [!NOTE] > Existing paying customers move onto Changemaker (with unlimited hours) until their renewal, > so nobody loses recording capacity in the transition. ## Requesting an upgrade If you're a [member](./roles-and-permissions.md#what-member-really-means-day-to-day) without billing rights, you don't pay the bill - you *request* an upgrade (a new workspace or a higher tier), and someone with billing rights, or dembrane staff, approves it. The same flow gates a few transitions, like [moving a workspace out of "open"](./visibility-and-discovery.md#the-one-paywalled-transition), which needs Innovator or above. ## Related - [Roles & permissions](./roles-and-permissions.md) - who can see invoices and change the plan. - [MCP & bring-your-own-LLM](./mcp-and-bring-your-own-llm.md) - the coming-soon Innovator integration. - [Data ownership & compliance](./data-ownership-and-compliance.md) - internal vs external billing and the sovereign stack. - [Organisations & workspaces](./organisations-and-workspaces.md) - what shares a billing account. - [Invites & access](./invites-and-access.md) - how seats are counted as you add people. - [Library & analysis](./library-and-analysis.md) - the built-in analysis Changemaker unlocks. --- # Account & security Everything personal to you lives under your user *Settings* - your display name, password, sign-in security, and preferences. These follow *you*, not any one [workspace](./organisations-and-workspaces.md). Anyone with an account can manage their own; no special role needed. ## Profile & display name Your *display name* is how you appear to others - in member lists, on [reports](./reports.md), and anywhere your activity shows up. Set it under account settings. A recognisable name (a real one, not a handle) helps collaborators and clients know who's who. ## Password Change your password from account settings. If you're locked out, the sign-in screen offers *password reset* by email - request it, follow the link, set a new one. New accounts confirm their email address before they're fully active. ## Two-factor authentication Turn on *two-factor authentication (2FA)* and signing in needs your password *and* a second factor, so a leaked password alone can't get in. > [!TIP] > If you handle conversations from real people - citizens, patients, employees - turn on 2FA. > It's the single biggest, cheapest improvement to your account's security. The > [dembrane Go](./mobile-app-dembrane-go.md) mobile app honours 2FA at sign-in too. ## Appearance & language Tune the interface to suit you - these change *your* view, not your colleagues': - *Font and size* - choose the typeface and text size for comfortable reading. - *Language* - the interface comes in eight languages: English (US), Dutch, German, French, Spanish, Italian, Ukrainian, and Czech. This doesn't affect the language of the conversations you record or the [transcription](./transcription.md), which is multilingual in its own right. > [!NOTE] > This documentation is in British English; the interface offers US English among its locales, > so small spelling differences (organize vs organise) between the docs and the UI are > expected. ## Audit logs An *audit log* records the actions taken in a workspace - a defensible trail of who did what and when. In regulated or high-stakes settings (public consultations, health, sensitive personal data) it's often a requirement rather than a nice-to-have. Audit logs are a [Changemaker](./tiers-and-billing.md) (or above) capability, surfaced to people who can manage the workspace. On Free or Innovator you'd [upgrade](./tiers-and-billing.md#requesting-an-upgrade) to reach it. See also [roles & permissions](./roles-and-permissions.md). ## Project defaults Account settings include *project defaults* that pre-fill choices when you create a new [project](./projects.md) - most importantly the *legal basis* for processing the conversations you collect. Setting a sensible default means every new project starts from a considered, consistent footing rather than a blank field, which matters when you're recording real people. The wider picture of who owns the data is in [data ownership & compliance](./data-ownership-and-compliance.md). ## What the assistant remembers about you *[dembrane next only](./dembrane-next.md).* If you use [Ask](./chat-and-ask.md), the assistant can save notes about how you like to work - saved during your chats, read back at the start of the next one. *Settings → Assistant* shows every note it keeps about you; only you see these, and *Remove* makes it forget one for every future chat. The assistant writes the notes; you can't edit them, only remove them. (Project and workspace notes have their own surfaces - see [chat & Ask](./chat-and-ask.md#more-than-analysis).) ## Your access at a glance A *my access* view lists the organisations and workspaces you belong to and the [role](./roles-and-permissions.md) you hold in each - the quickest answer to "what am I actually a member of, and as what?" To change any of it, you'd go through [invites & access](./invites-and-access.md) (and need the rights to do so). ## Deleting your account To comply with App Store and privacy guidelines, you can delete your account directly in the [dembrane Go](./mobile-app-dembrane-go.md) mobile app. When you initiate account deletion: - Your account is suspended immediately, which blocks logins and token refreshes. - This marks the account for permanent removal, which is processed out-of-band by dembrane administrators within 30 days. ## Related - [Roles & permissions](./roles-and-permissions.md) - your role decides what you can act on. - [Tiers & billing](./tiers-and-billing.md) - the tier that unlocks audit logs. - [Data ownership & compliance](./data-ownership-and-compliance.md) - legal basis and how data is handled. - [Invites & access](./invites-and-access.md) - how membership (and your "my access" list) changes. - [dembrane Go (the mobile app)](./mobile-app-dembrane-go.md) - sign-in, 2FA, and account deletion on mobile. --- # Using dembrane Go on mobile *dembrane Go* is the native iOS app for recording conversations away from a desk. Sign in with your dembrane account, pick a project, and record - it captures locally and robustly, then syncs into the same [projects](./creating-a-project.md) you use on the web, on the same transcription back end. A recording made on your phone is indistinguishable from a browser one once it lands. > [!IMPORTANT] > dembrane Go is in *beta* - it isn't on the App Store yet. To record on your phone today, > email [sameer@dembrane.com](mailto:sameer@dembrane.com) and we'll invite you to the > TestFlight beta. For the role-neutral reference, see [dembrane Go (the mobile app)](../../features/mobile-app-dembrane-go.md). ## Mobile or web? Reach for *dembrane Go* when you're *moving* (a walking interview, a site visit, a corridor chat), when you don't want to depend on a laptop and browser in the room, or when you want bulletproof local-first capture that survives the app being backgrounded, crashed, or killed. On background-capture UX the app is actually *ahead* of the web. Stick with the *web* when you want many people recording at once on their own devices - that's the [portal's](./collecting-conversations.md) job, not the app's - or when you need to set up a project, edit settings, or do analysis. > [!TIP] > A common pattern: send the crowd to the portal, and keep dembrane Go on your own phone for > the side conversations and interviews you run personally. ## What the app does - *Recording* - local-first capture in 30-second chunks, background recording, a Live Activity in the Dynamic Island, a waveform, and a microphone selector. You can also import an audio file. - *Conversations* - list and detail with transcript, summary, title generation, tags, move, delete, retranscribe, and edit. - *Ask / chat* - query your conversations with templates, history, sources, and a context picker. - *Search* - find conversations on the device. - *Portal settings* - edit the portal's title, description, and key terms, and share its QR code. - *Account* - switch project, sign out, and start account deletion (which completes in the browser). ## What syncs Conversations you record or import upload to the project you've selected and [transcribe](../../features/transcription.md) on the same pipeline as web recordings, so they appear in the dashboard alongside everything else - ready to read, tag, chat over, and report on. Portal settings you edit on mobile apply to the same portal your web participants use. ## What's web-only dembrane Go leaves the heavyweight "make sense and share" work to the dashboard. Not in the app: - *Library / analysis* - extracted topics, aspects, and quotes. - *Reports* - the report builder and PDF export. - the *full participant verification* flow. - *Project creation*, and *workspace / organisation / team* management. - *Billing detail*. - *Webhooks / export* and the *host guide PDF*. > [!IMPORTANT] > A clean division of labour: *record on mobile, understand and share on the web.* Anything > beyond recording and basic conversation management lives in the dashboard. ## A mobile-first session 1. Open dembrane Go and sign in (email and password; two-factor if you've enabled it). 2. Pick the project you want recordings to land in. 3. Record - let it run in the background while you move; the Live Activity keeps you informed. 4. Conversations sync and transcribe automatically. 5. Switch to the dashboard to [organise](./transcripts-and-conversations.md), [Ask](../../features/chat-and-ask.md), and [report](../../features/reports.md). ## Related - [dembrane Go (the mobile app)](../../features/mobile-app-dembrane-go.md) - canonical feature reference. - [Collecting conversations](./collecting-conversations.md) - how mobile fits the full set of methods. - [Recording](../../features/recording.md) - how capture works. - [Transcripts & conversations](./transcripts-and-conversations.md) - working with what you've recorded. - [Transcription](../../features/transcription.md) - turning audio into text. --- # Collecting conversations Collecting is getting spoken - or written - input into your [project](./creating-a-project.md). dembrane gives you several ways, and you can mix them within one project. The question that decides which fits is simple: *who is holding the device?* Before you start, make sure the [portal is set up](./portal-editor.md) (at least a title, description, finish message, and *key terms*). On *Free* you have *one hour* of recording; unlimited is on paid [tiers](../../features/tiers-and-billing.md). Uploading existing text doesn't use recording time. | Method | Who records | Best when | |---|---|---| | *Portal: QR or direct link* | The people themselves, on their own phones | Many people at once; self-service; in person or remote | | *Record yourself (browser)* | You, on a laptop | You're holding the conversation or interviewing | | *Upload text* | No one - you already have it | Migrating data, or audio captured elsewhere | | *dembrane Go (iOS, beta)* | You, on your phone | Mobile, walking, or flaky-laptop situations | ## The portal: QR or direct link The *portal* is a no-account web page people open to record for you - the default and most scalable way to collect. There are two ways to get people there: - *QR code* - auto-created and shown at the top of the project page. Open the host guide for a QR plus instruction page you can edit and download as a PDF to print. To scan, a participant opens their phone camera, points it at the code, and taps the link. - *Direct link* - copy and share the portal link by app, email, or browser, for people who aren't in the room. In the portal, participants can name their session (if you've enabled it), do a *mic check*, press start (a timer runs), and pause anytime. You can open and close the portal for participation, and see how many conversations are ongoing. Conversations show up in the dashboard as soon as they start; the transcript lands about 30 seconds to a minute later (audio is sent in 30-second pieces, and the higher-quality transcription takes a little extra processing). The full participant-side flow is in [the participant portal](../../features/portal-and-participant-experience.md). ### Watch the room: the Monitor page *[dembrane next only](../../features/dembrane-next.md).* During a live session, open *Monitor* in the project sidebar. It shows every participant from the moment they scan the QR, moving through *Scanned → Setting up → Recording* - so you spot the person stuck at the mic check while they're still in the room. Each live recording shows its state, duration, a level meter so you can see audio is actually arriving, and a live transcript snippet; if someone's audio stops coming in you get an *Audio stopped?* warning, and a locked phone shows as *Screen locked*. Transcription progress and errors show per conversation, with a rough *catch up* estimate when a backlog builds. The project home shows the same thing in brief under *Live & recent*. For a detailed walkthrough of all stages, indicators, and warnings, see [the live monitor](../../features/live-monitor.md) feature guide. > [!TIP] > Put the Monitor on your laptop while the room records. The two warnings worth acting on in > the moment: *Audio stopped?* (walk over, ask them to check their connection) and *Screen > locked* (ask them to wake their phone - recording pauses while it's locked). ### Ready Check Go (tell participants this before they record) A quick checklist that saves a lot of lost recordings: - Be on good *wifi or 5G*. - When prompted, *allow microphone access*. - *Keep the screen on* - a black screen means no recording. - A well-*charged phone* is less likely to sleep. - Turn on *Do Not Disturb* - better privacy, fewer interruptions. > [!TIP] > Print the QR large and test it from the back of the room. One line of spoken instructions > ("scan this, allow the microphone, and just talk") loses far fewer people at the start. ## Record yourself (in the browser) You can record a conversation yourself, right in the dashboard, from a laptop - good for one-to-one interviews, a panel you're moderating, or a meeting you're already in. Start a recording from within the project; dembrane captures in chunks, shows a level meter, and lets you pause, resume, and stop. See [recording](../../features/recording.md). ## Upload text If you already have conversation text - from another tool, a transcription service, or notes - bring it straight in without recording. Use the project's *upload* option to bulk-import transcripts; they become conversations you can read, tag, chat over, and report on like any other. Because nothing is recorded, this doesn't touch your recording hours. > [!NOTE] > dembrane is focused on moments of dialogue. Today the text-input route is the one way to > add extra written material; a more elegant document solution is coming soon. ## dembrane Go (the mobile app) [dembrane Go](./using-dembrane-go-mobile.md) is the native iOS recorder, built for capturing away from a desk: local-first recording in 30-second chunks that survives a crash or the app being killed, background recording, a Live Activity in the Dynamic Island, and a microphone selector. Sign in with your dembrane account, pick the project, and record - conversations sync to the same project and transcribe like browser recordings. dembrane Go is in *beta* - it isn't on the App Store yet. Email [sameer@dembrane.com](mailto:sameer@dembrane.com) to join the TestFlight beta. > [!IMPORTANT] > dembrane Go is a *recording* companion. Analysis, reports, the library, and project > creation stay on the web. Record on mobile; make sense of it in the dashboard. See > [what syncs and what's web-only](./using-dembrane-go-mobile.md). ## Choosing, in one breath - Lots of people, their own phones: *portal QR or link*. - You're doing the talking on a laptop: *record yourself*. - You already have the text: *upload*. - You're out and about: *dembrane Go*. ## After you've collected Recordings [transcribe automatically](../../features/transcription.md) and get a summary. From there, [read and organise](./transcripts-and-conversations.md) them, [Ask](../../features/chat-and-ask.md) questions across them, pull out themes with the [library](../../features/library-and-analysis.md), or assemble a [report](../../features/reports.md). ## Related - [The participant portal](../../features/portal-and-participant-experience.md) - the participant-side experience. - [Setting up the portal](./portal-editor.md) - configure that experience. - [Recording](../../features/recording.md) - how capture works. - [Using dembrane Go on mobile](./using-dembrane-go-mobile.md) - the iOS recorder. - [Transcripts & conversations](./transcripts-and-conversations.md) - what to do with what you've gathered. --- # Transcripts & conversations Once people have spoken, dembrane [transcribes](../../features/transcription.md) what they said and writes a summary. This is the day-to-day of working with that material: reading it, organising it, and keeping it accurate. Reading and organising is open to workspace *owners*, *admins*, *members*, plus *external* collaborators and *observers* (read-only); deleting is owner/admin/member only. For the role-neutral reference, see [conversations & transcripts](../../features/conversations-and-transcripts.md). ## When the transcript appears A conversation shows up in the dashboard as soon as it starts. The transcript follows about *30 seconds to a minute later*. Why the wait? Audio is sent in 30-second pieces, and the higher-quality transcription takes a little extra processing time. So a fresh conversation with no text yet is normal - give it a minute. ## The conversation list Each project has a *conversations* view listing everything collected. It's your home base: *search* across conversations, *filter* by tags and other attributes, and select several to apply *bulk actions* (below). ## Reading a conversation Open one to see: - *Transcript* - the full text in chunks. *Copy* it or *download a PDF*. - *Summary* - a short overview written by a language model. *Generate* it if it's not there yet, or *regenerate* it after a retranscribe or if the first pass missed the point. - *Tags* - labels you add to group related conversations. - *Verified artifacts* - the points a participant approved, if you used [verification](./portal-editor.md#the-optional-extras) in the portal. - *Anonymisation status* - whether personal information has been redacted. > [!NOTE] > Summaries are a starting point, not a verdict. They surface what's there so you can decide > what matters - read the transcript when a point is load-bearing. *People know how.* ## Tagging Tags make a pile of conversations navigable. Add tags that match the cuts you'll want later - by table, theme, sentiment, or location. Tagged conversations are easy to filter and to select as context for [Ask](../../features/chat-and-ask.md) and [reports](../../features/reports.md). If you set [portal tags](./portal-editor.md#the-optional-extras), conversations arrive pre-tagged. ## Locking *Locking* marks a conversation as settled and protects it from accidental changes. Lock the ones you've finished checking so a later bulk action doesn't touch them by mistake. ## Retranscribe If a transcript came out rough - heavy accents, a noisy room, jargon you hadn't listed - you can *retranscribe* it. First fill in your project's [key terms](./portal-editor.md#key-terms-the-highest-value-field), since they feed transcription. Afterwards, *regenerate the summary* so it reflects the improved text. > [!TIP] > A bad transcript is usually a missing-key-terms problem. Add the proper nouns and acronyms, > then retranscribe - the second pass is often markedly better. For detailed steps on fixing bad transcripts or summaries, see our [Troubleshooting transcripts & summaries](./troubleshooting-transcripts-and-summaries.md) guide. ## Anonymisation If you turned on [anonymise transcripts](./portal-editor.md#what-you-ask-of-participants) in the portal, dembrane redacts personal information as it processes each conversation, and the conversation shows its anonymisation status. Use it for sensitive topics and wherever you've promised anonymity - part of your broader [data ownership & compliance](../../features/data-ownership-and-compliance.md) responsibilities. ## Bulk actions Select several conversations in the list and apply: - *move* - relocate to another project; - *lock* - settle a batch in one go; - *delete* - remove conversations (owner/admin/member only); - *retranscribe* - re-run transcription across a batch. > [!WARNING] > Deleting is permanent and removes the transcript and audio. To just keep something out of > analysis, move it or filter it out rather than deleting. ## A clean post-session routine 1. Skim the list; *delete* obvious test recordings. 2. *Retranscribe* anything that reads badly (after checking key terms), then *regenerate* its summary. 3. *Tag* conversations by the cuts you'll want. 4. *Lock* the ones you've reviewed and are happy with. 5. Move on to [Ask](../../features/chat-and-ask.md) or a [report](../../features/reports.md). ## Related - [Conversations & transcripts](../../features/conversations-and-transcripts.md) - canonical feature reference. - [Transcription](../../features/transcription.md) - how audio becomes text, and why key terms matter. - [Setting up the portal](./portal-editor.md) - key terms, anonymisation, and verification are set here. - [Chat & Ask](../../features/chat-and-ask.md) - ask questions across tagged conversations. - [Reports](../../features/reports.md) - turn conversations into something shareable. --- # Chat & Ask *Ask* is the interactive way into your data. Instead of reading every transcript, you put questions to a set of [conversations](./conversations-and-transcripts.md) and get answers grounded in what people actually said, with the sources cited so you can check them. Treat it as a deep-dive, not a one-shot search: 1. *Start broad* - "What are the main themes?" 2. *Zoom in* - "What concerns came up about the bike lanes?" 3. *Ask for evidence* - "Show me the quotes." It's best for comparing viewpoints, finding quotes, and testing a hunch. ## One question bar > [!NOTE] > The new Ask experience is live on *[dembrane next](./dembrane-next.md)* and reaches > production with the next release. Click *Ask question* in a project and Ask opens as a home for all your chats, with one input: *Where would you like to start?* Press Enter and your question becomes a new chat; typing in the same bar also filters your earlier chats, so it finds an old thread as easily as it starts a new one. A *Templates* menu inserts a saved prompt. The assistant works in steps: it searches conversations, reads [transcripts](./conversations-and-transcripts.md), and chains what it finds to answer harder questions (*"find every conversation where someone disagreed with the proposal and tell me why"*). While it works you see its progress step by step, and a *Stop* control replaces *Send* so you can halt a run that's going the wrong way. Answers cite their sources by name - *"Maria's conversation"*, *"Maria's transcript excerpt"* - and each link jumps to the exact place in the transcript. ## The classic chat: Specific Details Prefer to pick the conversations yourself? One click on *Prefer the old chat? Start a Specific Details chat* starts a classic chat: you choose the conversations (or select all), optionally filtering by [tag](./conversations-and-transcripts.md#tags), and answers come back in one pass with exact quotes and citations. Best when every answer should come from the same fixed set: one session, one cohort, exact wording. If you're already viewing one conversation when you start, it's selected for you. The old *Overview* mode has been retired: its job - themes and patterns across all conversations - is covered by simply asking the assistant. ## More than analysis Beyond answering questions, the assistant can: - *Check what's live* - ask *"is anyone recording right now?"* and it reads the same live status as the [live monitor](./live-monitor.md). - *Read earlier chats* in the project (your colleagues' private chats stay private). - *Answer "how do I" questions* from this documentation, citing the page it used. - *Suggest settings changes* - it never edits your project itself; every change arrives as a proposal you review and apply (or reject). - *Log a question with the dembrane team* when you're stuck - see [getting help](../users/host/getting-help.md). - *Remember* - it can save notes about your preferences and the project so the next chat starts smarter. You can see and remove everything it remembers: your own notes under *Settings → Assistant*, project notes in project settings, workspace notes in [workspace settings](./organisations-and-workspaces.md). The assistant writes these notes; you can't edit them, only remove them. Hosts steer it with standing guidance too: the project *context* field, and a workspace-wide *assistant context* in workspace settings that reaches every project chat in the workspace. ## Cited sources Every answer lists the conversations it drew on. Click through to read a source in full on its [conversation page](./conversations-and-transcripts.md). If a claim matters, open the source and confirm it in the participant's own words. > [!TIP] > When pulling quotes for a [report](./reports.md), copy them from the cited source, not from > the chat answer - that way you're quoting the transcript, not a paraphrase. ## Templates & the prompt library You don't have to write every prompt from scratch: - *Built-in templates* live right in the chat - ready-made prompts for common tasks like summarising themes or surfacing disagreements. - *Save your own* so a question your team asks every project is one click away. - The *prompt library* has more, including patterns for large-scale, comparable analysis. Templates keep analysis consistent across projects and colleagues. > [!TIP] > Start small - a chat almost always gives more than you asked for. Sometimes that's a useful > nudge; often you don't need it. ## What you need Ask needs the `chat:use` permission, so *owner*, *admin*, *member* and *external* can use it; *observer* collaborators are read-only (see [roles & permissions](./roles-and-permissions.md)). The built-in analysis behind Ask is a *Changemaker* and *Guardian* feature, running on EU-hosted Gemini - chat that works out of the box. On *Free* it's limited. On *Innovator* you bring your own model instead: the chat screen becomes an integration where you connect ChatGPT or Claude over [MCP](./mcp-and-bring-your-own-llm.md) (*coming soon*). Where it isn't on your plan, dembrane asks what you need and offers you a call. See [tiers & billing](./tiers-and-billing.md). ## Chat vs library vs reports Three tools turn conversations into understanding, for different moments: - *Ask* (this page) - interactive, question-by-question. Best for exploring and pulling specific answers with sources. - *[Library & analysis](./library-and-analysis.md)* - a standing, automatically extracted view of topics, aspects and quotes across *all* your conversations. Best for large datasets where you want the whole landscape laid out. - *[Reports](./reports.md)* - a built, shareable document. Best when you're ready to communicate, not just explore. Most teams use all three: explore with Ask, see the landscape in the library, publish a report. ## Related - [Conversations & transcripts](./conversations-and-transcripts.md) - the material Ask reads, and where cited sources point. - [Library & analysis](./library-and-analysis.md) - the standing, extracted view for large datasets. - [Reports](./reports.md) - turn Ask findings into something you can share. - [Tiers & billing](./tiers-and-billing.md) - Free limits, Innovator BYO, Changemaker+ built-in analysis. - [MCP & bring-your-own-LLM](./mcp-and-bring-your-own-llm.md) - connect your own model on Innovator (coming soon). - [dembrane next](./dembrane-next.md) - preview features like the new Ask experience, not in production yet. - For a host's walkthrough, see [chat & Ask for hosts](../users/host/chat-and-ask.md). --- # Reports A *Report* is automatic synthesis. Click *Report* and dembrane analyses all your [conversations](./conversations-and-transcripts.md) at once - a few minutes - then gives you a document you can share by link or download as a PDF. It's the quickest way to capture the atmosphere of a session and the main questions that came up, and to put that in front of people who weren't in the room. Where [Ask](./chat-and-ask.md) is for exploring and [the library](./library-and-analysis.md) is for seeing the whole landscape, a report is for *communicating a conclusion* - to a steering group, a client, a council, or the participants themselves. ## Making one 1. Click *Report*. dembrane reads across the conversations and drafts the synthesis (a few minutes - longer the first time on a large batch, since it prepares the per-conversation summaries it builds on; later runs reuse them). 2. *Review* what came back. The draft is a starting point; the editorial judgement is yours. 3. *Share* the link or *download* the PDF to email, print, or attach. > [!TIP] > Get your [conversations](./conversations-and-transcripts.md) tidy and their summaries accurate > before you generate (see [reading a conversation](./conversations-and-transcripts.md#reading-a-conversation)). > A report reads from your material, so the cleaner the inputs, the less editing the output needs. ## Sending it to participants If you switched on participant updates in the [portal editor](./portal-editor.md), the report is *auto-sent to everyone who left an email* at the end of their recording - including people who couldn't attend. Great for post-event follow-up: collect, synthesise, and close the loop without chasing addresses. ## What you need Reports run on *built-in analysis*, so generating one needs a *Changemaker* or *Guardian* workspace. If the report option is greyed out, that's why. On *Free* and *Innovator* the built-in analysis isn't included; Innovator teams bring their own model via [MCP](./mcp-and-bring-your-own-llm.md) (coming soon). Where it isn't on your plan, dembrane asks what you need and offers you a call. See [what it costs](./tiers-and-billing.md#what-it-costs). By role: *owner*, *admin*, *member*, *external* and *observer* can *view* reports; everyone but *observer* can *generate*; *external* and *observer* can't *publish*. See [roles & permissions](./roles-and-permissions.md). ## When to use a report - Reach for a *report* when you're ready to *communicate* - you want a shareable document that captures what was found. - Reach for *[Ask](./chat-and-ask.md)* when you're still *exploring* - asking questions, pulling quotes, testing a hunch. - Reach for *[the library](./library-and-analysis.md)* when you want to *see the whole landscape* before you commit to a narrative. In practice these flow together: explore with Ask, map it with the library, then publish a report. > [!IMPORTANT] > A report is a draft written by a language model from your conversations. Read it against the > source before you share - dembrane surfaces what people said, but what you put your name to is > yours. ## Related - [Library & analysis](./library-and-analysis.md) - the standing structure a report draws on. - [Chat & Ask](./chat-and-ask.md) - explore and pull quotes before you write. - [Conversations & transcripts](./conversations-and-transcripts.md) - the source material and its summaries. - [The portal editor](./portal-editor.md) - switch on participant updates so reports auto-send. - [Export & data portability](./export-and-data-portability.md) - get the underlying data out, as opposed to a polished report. - [Tiers & billing](./tiers-and-billing.md) - reports need Changemaker or above. - For a host's walkthrough, see [reports for hosts](../users/host/reports.md). --- # Library & analysis > [!NOTE] > The *living canvas* and library analysis views are currently in *Beta* (available on the next-release *echo-next* environment only) and must be turned on per-project under *Project Settings* > *Experimental* > *Living canvas (Beta)*. The library lays out the whole landscape of a project. Where [Ask](./chat-and-ask.md) answers one question at a time, the library reads across all your [conversations](./conversations-and-transcripts.md) and surfaces: - *Topics* - the broad subjects people raised. - *Aspects* - the distinct angles within a topic. - *Quotes* - the actual things participants said, tied back to their source conversation. It's the tool for making sense of a *large* body of dialogue without reading every word - say, 200 interviews where you want the themes, with the evidence, laid out for you. You can also build *custom views*: your own lens on the material, organised the way your project thinks rather than the way the default extraction landed. Use one when the automatic structure is close but not quite your framing. ## Generating the library The library isn't live the instant a conversation lands - it's *generated* by reading across the conversations, which takes a moment for a big project. The page shows a status so you know whether it's building, up to date, or needs a refresh. When you've added a batch of conversations, retranscribed several, or changed your tags, *regenerate* it so the topics, aspects and quotes reflect the current material. Think of each generation as a snapshot of what the project says right now. > [!TIP] > Get your [conversations](./conversations-and-transcripts.md) in good shape - accurate > transcripts, sensible tags - *before* you generate. The library is only as good as the > material it reads. ## What you need The library is *built-in analysis*, so it needs *Changemaker* or *Guardian*, where analysis on EU-hosted Gemini is included. It isn't on *Free* or *Innovator*; on Innovator you bring your own model via [MCP](./mcp-and-bring-your-own-llm.md) (coming soon) and work through [Ask](./chat-and-ask.md) instead. Where it isn't on your plan, dembrane asks what you need and offers you a call rather than hiding the feature. See [what it costs](./tiers-and-billing.md#what-it-costs). Reading the library follows the same access as the rest of a project - *owner*, *admin*, *member*, *external* and *observer* can all read it; generating it is a host action (owner/admin/member). See [roles & permissions](./roles-and-permissions.md). ## Library vs Ask vs reports Three ways to turn dialogue into understanding, each with a sweet spot: - *Library* (this page) - the standing, full-picture structure. Best for *large datasets* where you want the whole landscape extracted and laid out to browse. - *[Ask](./chat-and-ask.md)* - interactive, one question at a time, with cited sources. Best for digging into a specific question or pulling a particular quote. - *[Reports](./reports.md)* - a built, shareable document. Best when you're ready to communicate. A common rhythm: use the library to see what's there, Ask to dig into what surprises you, then write a report to share the conclusion. > [!IMPORTANT] > The library extracts and organises; it doesn't decide what matters. Read the quotes behind a > topic before you treat it as a finding - the people who spoke are the authority, not the > extraction. ## Related - [Chat & Ask](./chat-and-ask.md) - interrogate the same conversations one question at a time. - [Reports](./reports.md) - turn the library's structure into a shareable document. - [Conversations & transcripts](./conversations-and-transcripts.md) - the source material, and where library quotes point back to. - [Tiers & billing](./tiers-and-billing.md) - the library needs Changemaker or above. - [MCP & bring-your-own-LLM](./mcp-and-bring-your-own-llm.md) - the Innovator alternative (coming soon). - For a host's walkthrough, see [library & analysis for hosts](../users/host/library-and-analysis.md). --- # Roles & permissions A role decides what someone can do. You pick one each time you invite a person. This page helps you choose, and shows exactly what each role can and can't do. ## Inviting someone? Pick the role | You want them to… | Give them | |---|---| | Run sessions and analyse the results - the everyday job | *member* | | Do all that *and* manage people, settings and billing | *admin* | | Have the final say over everything | *owner* | | See spend and invoices, but not the conversations | *billing* | | Collaborate from outside your organisation (edit, chat, build reports) | *external* | | Only *view* results, nothing else, for free | *observer* | Most teams need just two: *member* for people who run and analyse sessions, *admin* for the one or two people who also look after the workspace. > [!NOTE] > *observer* is free. Every other role uses a [seat](./tiers-and-billing.md#seats), which > counts towards your bill. Inviting is never blocked, though - you're billed for seats, not > stopped from adding people. ## What each role can do This is the full picture for a workspace. A tick means yes. | Action | owner | admin | member | billing | external | observer | |---|---|---|---|---|---|---| | View projects | ✓ | ✓ | ✓ | – | ✓ | ✓ | | Create projects | ✓ | ✓ | ✓ | – | – | – | | Edit projects | ✓ | ✓ | ✓ | – | ✓ | – | | Delete projects | ✓ | ✓ | – | – | – | – | | Read conversations | ✓ | ✓ | ✓ | – | ✓ | ✓ | | Delete conversations | ✓ | ✓ | ✓ | – | – | – | | Ask (chat) | ✓ | ✓ | ✓ | – | ✓ | – | | View reports | ✓ | ✓ | ✓ | – | ✓ | ✓ | | Build reports | ✓ | ✓ | ✓ | – | ✓ | – | | Invite & manage people | ✓ | ✓ | – | – | – | – | | Change settings | ✓ | ✓ | – | – | – | – | | See usage & invoices | ✓ | ✓ | usage only | ✓ | – | – | The shape to remember: *member* does the work, *admin* runs the place, *billing* sees only money, *external* is a paid helper from outside, *observer* just watches. ## Two outside-the-team roles *external* and *observer* are for people who aren't part of your organisation - a client, a consultant, a partner's contact. - *external* is a paid collaborator. They can edit projects, ask questions of the data, and build reports - but they can't create or delete projects, or invite anyone. - *observer* is free and read-only. They can open projects, read conversations, and view reports. Nothing else. It's the role for a client who should be able to *see* the work without touching it. Observers only exist in [external-client workspaces](./partner-program.md) (the ones a partner runs for someone else), and the data owner is added as one automatically. To turn an observer into a paid *external* collaborator, an admin just changes their role. Turning an outside collaborator into a full team *member* is a bigger step (it brings them into your organisation), so it's done deliberately: remove them, add them to the organisation, then re-invite as a member. ## Organisation vs workspace dembrane has two levels, and roles exist at both: - An *organisation* is your company's account. Organisation roles decide who can create new workspaces and who sees billing across all of them. - A *workspace* is where projects live. Workspace roles (the table above) decide who can do what with the actual work. Most people only ever need a workspace role. You can belong to a workspace without being in the organisation at all - that's what *external* and *observer* are. See [organisations & workspaces](./organisations-and-workspaces.md) for how the levels fit together. The organisation roles mirror the workspace ones: *owner* (full control), *admin* (manage people, settings, billing, and create workspaces), *member* (belongs to the org, does their work in workspaces), and *billing* (sees spend across every workspace, touches no content). ## Two rules worth knowing - *You can't give someone a role above your own.* An admin can invite members and other admins, but not an owner. See [invites & access](./invites-and-access.md). - *dembrane staff have separate powers* (changing your tier, moving a workspace) that aren't part of these roles. If you're staff, see the [staff guides](../users/staff/index.md). ## Related - [Invites & access](./invites-and-access.md) - how you actually add people and set roles. - [Tiers & billing](./tiers-and-billing.md) - what a seat costs and what each plan includes. - [Organisations & workspaces](./organisations-and-workspaces.md) - the two levels roles live in. - [The partner program](./partner-program.md) - where external and observer collaborators fit. --- # What to expect Taking part is quick and follows a simple path. Here's the whole thing, so there are no surprises. > [!NOTE] > You won't always see every step. The person who set up the session chooses which parts to > include, so yours may be shorter. If a step below doesn't appear, that's by design. ## 1. Open the link or scan the code You'll have a *link* to tap or a *QR code* to scan with your phone's camera. Either one opens the session in your normal web browser - nothing to install, no account. ## 2. A few welcome cards A short series of cards will welcome you, explain what the session is about, give a little guidance on taking part, show how your privacy is handled (with a link to the [privacy statement](./your-privacy-and-data.md)), and ask you to *agree to take part* before anything is recorded. You may also be asked to choose a language. Take a moment with these. ## 3. Maybe a question or two Some sessions ask for your *name*, some for an *email* - both optional, and decided by the person who set things up. An email is usually just so a summary can be sent to you afterwards. If you'd rather not give either, that's between you and them. See [your privacy & your data](./your-privacy-and-data.md). ## 4. A microphone check Before you start, you'll do a short *microphone test*. Your browser will ask permission to use the microphone - say yes, and you'll see a little level indicator move when you speak. If it doesn't work, [recording your conversation](./recording-your-conversation.md#if-the-microphone-isnt-working) has the fixes. ## 5. Record The main event: you talk, and dembrane records. A level meter shows you're being picked up. You can pause and resume whenever you like, and stop when you're done. Prefer not to speak? Most sessions let you *type instead* - see [recording your conversation](./recording-your-conversation.md). ## 6. Maybe look back over what you said Some sessions invite you to review afterwards: *refine* (look over the parts you recorded and choose what to keep) and *verify* (check that the points dembrane picked up are right, and approve or tidy them). Both are explained in [refining & verifying](./refining-and-verifying.md). If your session skips them, you go straight to finishing. ## 7. Finish You'll see a thank-you message. That's it - you're done. If it's been turned on, you may also be offered a [report](./your-report.md): a short summary you can read for yourself. ## Related - [Recording your conversation](./recording-your-conversation.md) - recording well, pausing, stopping, typing, and troubleshooting. - [Refining & verifying](./refining-and-verifying.md) - reviewing what you said. - [Your privacy & your data](./your-privacy-and-data.md) - what happens to your words. - [Your report](./your-report.md) - the summary you might see at the end. --- # Recording your conversation Recording is meant to feel as easy as talking. Here's how to be heard clearly, how the controls work, how to type instead of speak, and what to try if something goes wrong. ## Before you start A few things set you up well: - *Good signal.* Be on solid wifi or 5G. - *Allow the microphone* when your browser asks. - *Keep the screen on.* A black screen means no recording. A well-charged phone is less likely to fall asleep. - *Turn on Do Not Disturb* for more privacy and fewer interruptions. ## Recording well - *Find a quieter spot* if you can. A bit of background noise is fine; a busy café is harder. - *Speak as you naturally would* - no need to slow down or talk like a robot - towards your phone or laptop. - *Watch the level meter.* If it's barely moving, you may be too far from the microphone or speaking too softly. - *Take your time.* Pauses are fine. There's no rush, and you can stop and start as much as you like. ## Pause, resume and stop - *Pause* - take a break. Nothing is lost; the recording waits for you. - *Resume* - pick up where you left off. - *Stop* - finish when you've said what you want to say. > [!TIP] > Interrupted by a phone call or someone walking in? Just *pause*, and *resume* when you're > ready. Your recording is saved as you go, so a short break is no problem. ## Typing instead of speaking Somewhere you can't talk freely, or simply prefer to write? Most sessions offer a *type-instead* option - look for the choice to type your contribution, and write it out. Your words are treated exactly the same way. ## If something isn't working Most hiccups are quick to fix. ### If the microphone isn't working - *Allow microphone access.* If you said no or missed the prompt, look for a small microphone icon in your browser's address bar, switch it on, and reload the page. - *Close other apps* that might be using the microphone (a video call, a voice recorder). - *Check your device isn't muted*, and that the right microphone is selected if you have more than one. - *Test it.* Speak and watch the level meter; if it doesn't move, the microphone isn't being picked up yet. ### If the connection drops dembrane sends your recording as you go, in small pieces, so a brief wobble usually isn't a problem - it catches up. If you see a message about the connection or saving: - *Stay on the page* a moment to let it catch up. - *Check your internet* - switching to better wifi can help. - *Don't close the tab* until you've seen the finish or thank-you screen. ### If you see an echo or spike warning Sometimes the recorder notices an *echo* or a sudden *spike* in sound and lets you know. It's just a nudge for quality - move somewhere quieter, lower a nearby speaker, or hold the device a little differently, then carry on. > [!NOTE] > If something still won't work, the person who invited you is the best first port of call - > they set up the session and can help or try again. ## Related - [What to expect](./what-to-expect.md) - where recording fits in the whole flow. - [Refining & verifying](./refining-and-verifying.md) - looking back over what you recorded. - [Your privacy & your data](./your-privacy-and-data.md) - what happens to your recording. --- # Refining & verifying Some sessions invite you to look back over what you said before you finish. It's a chance to make sure you're happy with what you've shared, and that it was understood correctly. You're in charge - nothing is set in stone until you say so. > [!NOTE] > Not every session includes these steps. If you go straight from recording to a thank-you > screen, that's normal. ## Refining - choosing what to keep You might be shown the *parts* of what you said and asked to review them. Look back over each one and *choose what to keep* and what to leave out. Think of it as tidying up before you hand something in: if you said something you'd rather not include, leave it out. Keep what represents you well. ## Verifying - checking the points dembrane can pick out the key points from what you said - the main things you raised. If your session includes *verification*, you'll see those points (and maybe a few topics to focus on) and be asked to check each one. You can: - *approve* it, if it captures what you meant, - *edit* it, if it's close but not quite right, or - *reject* it, if it's not something you want to stand behind. dembrane does the first pass of picking out points, but *you have the final word*. It's your meaning, so you decide what's carried forward. > [!TIP] > Read each point as "is this what I meant?" rather than "is this word-for-word what I said?". > A fair summary can be true to you even without your exact words. Whether you're refining or verifying, you choose what to keep and confirm what's right. Happy to leave it as is? Just approve and move on to the [finish](./what-to-expect.md#7-finish) step. ## Related - [What to expect](./what-to-expect.md) - where these steps sit in the whole flow. - [Recording your conversation](./recording-your-conversation.md) - the step that comes before. - [Your privacy & your data](./your-privacy-and-data.md) - what happens to the points you approve. - [Your report](./your-report.md) - the summary you might see at the end. --- # Your privacy & your data When you share your thoughts with dembrane, you deserve to know what happens to them. Here it is, plainly. ## What happens to your words When you speak or type, dembrane *records* what you share, *transcribes* it - turns the audio into written text - securely, and *helps the organiser make sense of it* alongside what other people shared, as summaries and themes. The point is never to single you out. It's to help the organiser understand what a *group* of people said, so everyone's input counts. ## Keeping you anonymous dembrane can *anonymise* transcripts - removing or hiding personal details so the written record doesn't point straight back to you. Many organisers turn this on, so the focus stays on *what* was said rather than *who* said it. If you're unsure whether a session does this, the welcome cards and the privacy statement are the place to check, and the organiser can confirm. ## Agreeing to take part Nothing is recorded until you've agreed to take part - that's why the welcome cards include a clear consent step before recording begins. You're never recorded by surprise. Change your mind partway through? Just *stop* and don't finish. After the session, you can also [opt out](#opting-out). ## Your privacy, plainly - *You don't need an account*, so you're not creating a profile or a login. - *You're only asked for a name or email if the organiser chose to ask* - and even then it's your choice. An email is usually only so a summary can be sent to you. - *Your data is handled to a European standard.* dembrane is built with GDPR - Europe's data protection rules - in mind: clear consent, keeping data to what's needed, and respecting your right to withdraw. - *The full details are in the privacy statement* linked from the welcome cards. > [!NOTE] > dembrane gives organisers the tools to handle your data responsibly. How a particular session > uses them is up to the organiser, so their privacy statement is the most accurate word for > *your* session. ## Opting out - *During a session* - if you'd rather not continue, just *stop*. You don't have to finish. - *If you gave an email* and later don't want to hear more, use the *unsubscribe* option to opt out of further messages. - *To have your contribution removed* afterwards, contact the person who invited you - as the organiser, they're responsible for the data they collect and can act on your request. > [!TIP] > Keep the link or message that invited you. It's the easiest way to find your session again > and to reach the organiser about your data. ## Related - [What to expect](./what-to-expect.md) - the consent and welcome steps in context. - [Recording your conversation](./recording-your-conversation.md) - stopping at any time. - [Refining & verifying](./refining-and-verifying.md) - choosing what to keep. - [Your report](./your-report.md) - the summary you might be shown. --- # Your report Some sessions offer you a *report* at the end: a short summary made from what you shared, for you to read for yourself. It's a small thank-you and a way to close the loop, so you can see your words led somewhere. > [!NOTE] > A report only appears *if the organiser turns it on*. Many sessions don't include one, and > that's perfectly normal - it doesn't mean anything went wrong or that your input wasn't > valued. ## What it shows A tidy version of your own contribution - a summary and the main points drawn from what you said. It's a clear, readable reflection of what you shared, not a transcript of every word. The exact look and length depend on how the organiser set things up, so two sessions can offer slightly different reports. ## How you'll see it - *At the finish* - you may be offered the report right away on the final screen. - *By email* - if you gave an email and the organiser chose to send summaries, the report (or a link to it) may arrive in your inbox. Don't want emails about it? You can [unsubscribe](./your-privacy-and-data.md#opting-out). ## What it's for The report is yours to read - a record of what you brought to the conversation. The organiser, meanwhile, brings everyone's contributions together to understand what the *group* said. Your report is your own slice of that bigger picture. > [!TIP] > To see what happens to your words beyond your own report, read > [your privacy & your data](./your-privacy-and-data.md). ## Related - [What to expect](./what-to-expect.md) - where the report sits in the flow. - [Refining & verifying](./refining-and-verifying.md) - checking the points that feed into it. - [Your privacy & your data](./your-privacy-and-data.md) - how your words are handled, and how to unsubscribe. --- # Transcription Transcription turns recorded audio into text, automatically. As soon as [recording](./recording.md) produces audio, dembrane transcribes it, cleans it up, and stitches it into a transcript you can read, search and [ask questions of](./chat-and-ask.md). It's automatic on every tier - *secure transcription is included even on Free* (see [tiers & billing](./tiers-and-billing.md)). ## Secure and multilingual dembrane transcribes in dozens of languages and copes with people switching language mid-sentence, so people can speak naturally, in their own language, and still get a faithful transcript. Audio is handled on infrastructure dembrane controls, and where data needs to stay in the EU that can be arranged - see [data ownership & compliance](./data-ownership-and-compliance.md). A project has a default [conversation language](./projects.md), but participants record in their own, and the [portal](./portal-and-participant-experience.md) can be offered per language so the whole experience matches the speaker. ## Key terms After the first draft, a language model cleans up the transcript - and the most useful thing you can give it is a list of *key terms*: the proper nouns, names and jargon you want spelled right. Set them in the [portal editor](./portal-editor.md). Without "dembrane" in that list, for instance, it gets misspelled across your transcripts. > [!TIP] > Spend two minutes on key terms before an event. A handful of names and acronyms is the > difference between "Ms Janssen, the alderman" and three different spellings of the same > person. ## Anonymisation Turn on anonymisation (per project, in the [portal editor](./portal-editor.md)) and identifying details spoken aloud - names and the like - are removed before the transcript is stored, so it can be shared and analysed without exposing who said what. A conversation's [detail view](./conversations-and-transcripts.md) shows its anonymisation status, so you always know whether what you're reading has been cleaned. > [!IMPORTANT] > Decide on anonymisation *before* you collect, where you can. Whether names are redacted is a > privacy choice about the people in your room - cleaner to set the expectation up front than to > change course halfway through. ## Re-transcribing Changed your key terms, turned anonymisation on, or simply weren't happy with a result? You can *re-transcribe* a conversation - or a batch of them - from the [conversations](./conversations-and-transcripts.md) view. dembrane re-runs on the original audio and replaces the transcript. The audio is the source of truth, so this is safe to do as often as you need. ## Related - [Recording](./recording.md) - where the audio comes from. - [The portal editor](./portal-editor.md) - where you set key terms and anonymisation. - [Conversations & transcripts](./conversations-and-transcripts.md) - reading, editing and re-transcribing the result. - [Data ownership & compliance](./data-ownership-and-compliance.md) - how transcripts are stored and kept private. --- # Export & data portability Your conversations, transcripts, and findings are *yours*, and dembrane makes them easy to take with you. Download a single transcript, export a whole project's transcripts as a zip, pull structured data as CSV or Excel, export a [report](./reports.md) as a PDF, or fetch everything over the API. At any point you can get your data out, in formats other tools understand. If you can read a conversation, you can export its transcript - [most roles that read content](./roles-and-permissions.md) can export it. Whole-workspace export is an admin capability; automated API export is for developers, covered in [export & integrations](../users/developer-external/export-and-integrations.md). ## What you can export *A single transcript.* From a [conversation's](./conversations-and-transcripts.md) detail view, *copy* the text to your clipboard, *download a PDF*, or pull the plain text via the API (`GET /api/conversations/{cid}/transcript`). *A whole project's transcripts.* Export all of a project's transcripts at once as a *zip*, each conversation its own Markdown file (`GET /api/projects/{pid}/transcripts`). The fastest way to hand someone a complete, readable record. *CSV / Excel.* From a project's *integrations / export* area, export structured data as CSV or Excel - the right choice for analysing in a spreadsheet or feeding another tool. *Reports.* A [report](./reports.md) you've built exports as a *PDF*: the assembled, multi-section document, ready to share or print. Reports can also be scheduled and emailed. ## Where to find it - *On a conversation* - copy and PDF download, in the detail view. - *In the project's integrations / export tab* - the transcript zip, CSV/Excel, and the entry point to [webhooks](./webhooks-and-integrations.md). > [!TIP] > For a one-off handover, the *transcript zip* plus a *report PDF* usually covers it - the > raw record plus the synthesis. For anything recurring, reach for the API. ## The API, for recurring exports Everything above can be done by hand, but if you need it regularly, dembrane exposes the same data over its API - pulling transcripts on a schedule into your own warehouse, triggering exports from your tooling, or combining export with [webhooks](./webhooks-and-integrations.md) so a finished report flows straight into your systems. Endpoints, auth, and patterns are on [export & integrations](../users/developer-external/export-and-integrations.md). > [!NOTE] > Export gives you the *output* and the API automates pulling it. If your goal is to *react* > to events - a conversation finished, a report generated - rather than pull on demand, look > at [webhooks & integrations](./webhooks-and-integrations.md) instead. ## Related - [Reports](./reports.md) - building the documents you export as PDF. - [Conversations & transcripts](./conversations-and-transcripts.md) - where per-conversation copy and download live. - [Export & integrations (developer)](../users/developer-external/export-and-integrations.md) - the API endpoints and automation patterns. - [Webhooks & integrations](./webhooks-and-integrations.md) - push events to your own systems instead of pulling. --- # Getting help Something not working, or a question this documentation does not answer? These are the ways to reach us, fastest first. ## Ask in the app The *[Ask](./chat-and-ask.md)* chat can log a question or problem with the dembrane team for you. Describe what happened and ask it to pass the issue on. It will show you what it sends before sending. Logged requests go into the team's review queue; they are read, but this route does not guarantee a direct reply. ## Email the team For anything that needs a person to respond, email *support@dembrane.com*. Include: - the workspace and project name - what you were doing and what you expected - when it happened, so we can find it in our logs For privacy questions or objections about participant data, use *info@dembrane.com*. ## Join the community The dembrane community Slack is where hosts share how they run sessions and where the team hangs out. Ask for the invite link from the Help section in the app sidebar. ## If the in-app route fails Logging a request through Ask can occasionally fail, like any network call. When it does, email *support@dembrane.com* directly with the same details. Nothing is lost by switching channels; email always reaches us. --- # Observer & external collaborators When you run a workspace for a client you'll usually want to bring them in - but how far in depends on the moment. dembrane gives you two outside-the-organisation roles for it: - *observer* - free, read-only. The client can watch, but can't touch. Use it when they should *see* findings as they land without changing anything, and you don't want to charge a seat. It's the default for the data owner on every [external-client workspace](./external-client-workspaces.md). - *external* - a paid collaborator. The client, or an outside consultant, can edit projects, read conversations, [chat](../../features/chat-and-ask.md) and generate [reports](../../features/reports.md). Use it when they need to roll up their sleeves. Both render grey in member lists, and both really come into their own inside [external-client workspaces](./external-client-workspaces.md). Inviting people and changing roles needs workspace *owner* or *admin* rights. The canonical breakdown is in [roles & permissions](../../features/roles-and-permissions.md). ## At a glance | | observer | external | |---|---|---| | Cost | *free* - no seat | *paid* - takes a seat | | Read projects | ✓ | ✓ | | Edit projects | ✗ | ✓ | | Create / delete projects | ✗ | ✗ | | Read conversations | ✓ | ✓ | | Use chat | ✗ | ✓ | | View reports | ✓ | ✓ | | Generate reports | ✗ | ✓ | | Publish reports | ✗ | ✗ | | Invite / manage members | ✗ | ✗ | | Where it exists | external-client workspaces only | any workspace | The free observer is the floor of the role hierarchy: read everything, change nothing. An external collaborator joins an existing project to work in it - they edit, chat and generate, but don't create or delete projects, record, invite, manage settings, or publish reports. They run nothing; they contribute. ## Upgrading an observer to external There's a clean path from watching to contributing: a workspace *admin* changes the person's role from *observer* to *external*. From that moment they can edit, chat and generate - and they start consuming a paid seat. > [!TIP] > Start clients as observers. It costs nothing, reassures them their data is theirs, and > upgrading to external is a one-step role change the moment they need to do more. Going *further* - turning an external collaborator into a full *member* of your organisation - is deliberately not one click, because it brings them *into* your org. That cross-table move is described in [roles & permissions](../../features/roles-and-permissions.md). ## Choosing the right role - The client should just *watch*, at no cost - *observer*. - The client or an outside consultant should *edit, chat or generate* - *external*. - Someone is really part of *your* organisation now - bring them in as a *member* (see [roles & permissions](../../features/roles-and-permissions.md)). ## Related - [Roles & permissions](../../features/roles-and-permissions.md) - the full capability matrix. - [External-client workspaces](./external-client-workspaces.md) - where observer and external live, and the auto-invited observer. - [Data ownership & handoff](./data-ownership-and-handoff.md) - the data owner is your first observer. - [Tiers & billing](../../features/tiers-and-billing.md) - seats, and what external costs. --- # Becoming a partner Partner status belongs to an *organisation*, not a person. Once dembrane marks your org as a partner, every host in it can run *external-client workspaces* - workspaces that belong to, and bill to, someone outside your organisation. You can't toggle it yourself. It's a dembrane staff action that comes with a partner agreement, so it starts as a conversation, not a button in your settings. You'd want it when your org routinely does dembrane work for other people: an agency running engagements for several municipalities that each own their data, a consultancy billing each client separately and handing over at the end, a research group where the commissioning body is the data owner. If all your work is for your own org, you don't need it - the ordinary [host](../host/index.md) experience covers you. ## How it happens 1. *Talk to dembrane.* Partner status comes with an agreement, so it begins as a conversation. 2. *Staff set the flag.* A dembrane staff member turns on the partner toggle for your org. 3. *The abilities appear.* Hosts who are workspace *owner* or *admin* can now create external-client workspaces, and the [data-ownership](./data-ownership-and-handoff.md) controls show up on them. > [!NOTE] > Your existing *internal* workspaces don't change when your org becomes a partner. They keep > sharing the org's pooled billing and branding. Partner status only adds a new *kind* of > workspace you can create. ## What it unlocks Once you're a partner, hosts can: - *Create external-client workspaces* with their own [separate billing](./external-client-workspaces.md#workspace-scoped-billing). - *Name a data owner* and have them [auto-invited as a free observer](./observer-and-external-collaborators.md). - *Use the free observer role* - read-only eyes for a client at no cost, only in external-client workspaces. - *Whitelabel* an external-client workspace with the client's own logo (external-only). - *Hand a workspace off* to the client when the engagement ends - see [data ownership & handoff](./data-ownership-and-handoff.md). Partners may also take part in [referral](./referrals.md) arrangements dembrane staff administer. ## The partner agreement Running dembrane for other people carries responsibilities around how their data is held and handed over. Those are set out in a *partner agreement* between your org and dembrane. It also surfaces *per workspace*: when you create an external-client workspace, you tick a partner-agreement checkbox as you name the data owner, and dembrane records the moment you accept. See [external-client workspaces](./external-client-workspaces.md#the-data-owner-step) for that step. > [!IMPORTANT] > The legal terms of the agreement come from dembrane, not from this documentation. If you're > not sure what you're agreeing to, ask before you accept. ## Related - [External-client workspaces](./external-client-workspaces.md) - what you create once you're a partner. - [Data ownership & handoff](./data-ownership-and-handoff.md) - the responsibilities that come with it. - [The partner program](../../features/partner-program.md) - the canonical reference. - [Referrals](./referrals.md) - kickback and discount arrangements for partners. - [Roles & permissions](../../features/roles-and-permissions.md) - observer and external. --- # External-client workspaces An *external-client workspace* is one you run on behalf of someone outside your organisation. Where an ordinary internal workspace shares your org's pooled billing and branding, an external-client workspace: - *names a data owner* (the client), - *bills on its own*, - *auto-invites the data owner as a free [observer](./observer-and-external-collaborators.md)*, and - can be *whitelabelled* with the client's own logo. Create one whenever the data really belongs to the client - a municipality's citizen panels, a client you'll bill separately, work you expect to [hand over](./data-ownership-and-handoff.md) once it's done. For work that's for your own organisation, create an ordinary internal workspace instead. You'll need to be a workspace *owner* or *admin* inside a [partner](./becoming-a-partner.md) org. ## Creating one - the data-owner step When you create a workspace as a partner, mark it as belonging to an external client. That asks for three things: 1. *Client / data-owner organisation name* - who the data belongs to. 2. *Data-owner email* - the person at the client who owns the data. This is the address that gets auto-invited as a free observer, and the one dembrane uses to recognise the data owner in workspace lists. 3. *Partner-agreement checkbox* - you confirm the [partner agreement](./becoming-a-partner.md#the-partner-agreement) for this engagement, and dembrane records the moment you tick it. On submit, dembrane marks the workspace as external-client, gives it its own billing account, and auto-invites the data owner as a free observer. > [!TIP] > Get the data-owner email right. It decides who's invited as the observer *and* lets dembrane > show that person a "you are the data owner" marker in their workspace list - a small, > privacy-respecting touch that reassures the client the data is theirs. ## Separate billing An external-client workspace gets its *own* billing account rather than drawing on your org's pool. That's the point: each client's usage and spend stays cleanly apart from yours and from every other client, and it makes a clean [handoff](./data-ownership-and-handoff.md) possible later. For what's metered and how seats count, see [tiers & billing](../../features/tiers-and-billing.md). > [!NOTE] > The free observer doesn't take a seat, so auto-inviting the data owner costs nothing. Paid > roles - including [external](./observer-and-external-collaborators.md) collaborators - do > count towards the workspace's own bill. ## The auto-invited free observer Every external-client workspace starts with the data owner already invited as a free, read-only observer. They can open projects, read conversations and view reports - and nothing more (no chat, generate, edit or invite). The client can *see* their own data being handled from day one, without you having to remember to add them and without it costing a seat. When they need to do more, an admin upgrades them from observer to [external](./observer-and-external-collaborators.md#upgrading-an-observer-to-external). The observer role only exists here - internal workspaces reject observer invites. Full details in [observer & external collaborators](./observer-and-external-collaborators.md). ## Whitelabel External-client workspaces can be *whitelabelled* - given the client's own logo in place of the inherited branding. This is external-only; internal workspaces inherit your org's branding. It makes the workspace feel like the client's own, which matters when participants record into it and when the client eventually takes it over. > [!NOTE] > Whitelabel arrives with a *Changemaker* workspace or above. See > [tiers & billing](../../features/tiers-and-billing.md) for what each plan unlocks. ## Related - [Data ownership & compliance](../../features/data-ownership-and-compliance.md) - internal versus external workspaces and who owns the data. - [Data ownership & handoff](./data-ownership-and-handoff.md) - naming a data owner and handing the workspace over. - [Observer & external collaborators](./observer-and-external-collaborators.md) - the free and paid client roles. - [Becoming a partner](./becoming-a-partner.md) - you need partner status to create these. - [Tiers & billing](../../features/tiers-and-billing.md) - seats, metering, whitelabel gating. --- # Data ownership & handoff When you run dembrane for a client, the recordings, transcripts and reports are *theirs*, not yours. This page is about making that explicit and honouring it: naming the data owner, moving work into the right place, and eventually handing the whole workspace over. You'll need it when you're setting up an [external-client workspace](./external-client-workspaces.md), when a project that started in your internal workspace now belongs in the client's, or when an engagement ends and the client wants to take over. Naming a data owner and moving projects is workspace *admin* / *owner* work; transferring a whole workspace is a dembrane staff action. All of it assumes your org is a [partner](./becoming-a-partner.md). ## Naming a data owner You name the data owner when you create an [external-client workspace](./external-client-workspaces.md#the-data-owner-step), by giving the client organisation name, the data-owner email, and a confirmation of the [partner agreement](./becoming-a-partner.md#the-partner-agreement). All three are editable afterwards. dembrane uses the data-owner email to recognise the owner: when the signed-in user's email matches it, their workspace list shows a *"you are the data owner"* marker - a privacy-respecting signal (it doesn't expose the email to everyone) that tells the client this workspace's data is theirs. The data owner is also [auto-invited as a free observer](./observer-and-external-collaborators.md), so they can watch from day one. The agreement is what makes the handoff trustworthy: the promise that the data is the client's and that you'll hand it over cleanly when asked. For the wider picture - GDPR posture, anonymisation, EU-sovereign options - see [data ownership & compliance](../../features/data-ownership-and-compliance.md). ## Moving projects Work doesn't always start in the right place. - *Move a project* between workspaces - say, lifting one out of your internal workspace into the client's external-client workspace - from the project's *Settings - Overview - Move project*. Owner/admin only. You can also bulk-move conversations between projects. See [projects](../../features/projects.md). - *Transfer a whole workspace* to a different owner - the partner-to-client handoff, below. > [!TIP] > Because an external-client workspace already has its own > [separate billing](./external-client-workspaces.md#workspace-scoped-billing), moving a > project into it cleanly re-homes that work under the client's account rather than yours. ## Handing a workspace off Many partner engagements end with the client taking over. Because an external-client workspace already stands on its own - its own billing, its own data owner, optionally its own [whitelabel](./external-client-workspaces.md#whitelabel) - handoff is mostly a matter of transferring ownership. That transfer is a dembrane staff action, so it runs through dembrane rather than a button in your settings. A typical handoff: 1. Make sure the work is all in the right workspace - move any stray [projects](../../features/projects.md) in first. 2. Upgrade the client from [observer to external](./observer-and-external-collaborators.md#upgrading-an-observer-to-external), or bring them into their own organisation, so they have the access they'll need. 3. Ask dembrane staff to transfer the workspace to the client. ## Related - [Data ownership & compliance](../../features/data-ownership-and-compliance.md) - internal vs external, GDPR posture, anonymisation. - [External-client workspaces](./external-client-workspaces.md) - where the data owner is named and billing stands alone. - [Observer & external collaborators](./observer-and-external-collaborators.md) - the data owner's starting role, and upgrading it. - [Projects](../../features/projects.md) - moving projects between workspaces. - [Becoming a partner](./becoming-a-partner.md) - the agreement that underpins all of this. --- # Referrals When a partner brings business to dembrane - or passes a discount on to a client - the arrangement is tracked in a *referral ledger*. Each deal records a kickback percentage, a discount percentage, a cap in euros, and an expiry: a partner brings a customer, the customer may get a discount, and the partner may receive a kickback, up to the cap, until the deal expires. The ledger is *administered by dembrane staff*. It isn't self-serve, and there's no role that opens it to editing. As a partner you benefit from these arrangements; you agree the terms with dembrane and they record them for you. If none of this describes your engagement, skip this page - referrals are an optional commercial layer on top of ordinary [partner](./index.md) work. ## What you see The outcome of your arrangements, rather than the controls: - the *terms you've agreed* with dembrane for each deal, and - the discounts your *clients* receive, reflected in their [workspace-scoped billing](./external-client-workspaces.md#workspace-scoped-billing). > [!NOTE] > Want the running total or current state of a referral arrangement? Ask your dembrane contact. > The ledger lives on the staff side; they can read it back to you. > [!IMPORTANT] > Exact kickback and discount figures are commercial terms agreed with dembrane, not values > this documentation can quote. Confirm the numbers with dembrane before relying on them. ## Related - [Partner overview](./index.md) - the rest of the partner toolkit. - [External-client workspaces](./external-client-workspaces.md) - where a client's discounted billing shows up. - [Becoming a partner](./becoming-a-partner.md) - the precondition for these arrangements. - [Tiers & billing](../../features/tiers-and-billing.md) - how pricing and seats work before any discount. --- # The partner program If you facilitate sessions and analyse the results *for* someone else - a municipality, a client, a community - the partner program is built for you. Your organisation becomes a *partner*: it hosts a separate workspace for each client engagement, keeps each client's data cleanly boxed off, names the client as the data owner, and can hand the whole thing over when the work is done. A few signs it's for you: you run a citizens' assembly that the municipality owns; you interview a client's customers and want them to *see* the findings without paying for a seat; you run dozens of short engagements a year and need each one isolated, billed separately, and easy to transfer at the end. Only dembrane *staff* can mark your organisation as a partner. You can't toggle it yourself - ask your dembrane contact, or see [becoming a partner](../users/host-partner/becoming-a-partner.md). Once you're a partner, any of your workspace [admins](./roles-and-permissions.md) can create external-client workspaces. Being a partner doesn't change your own tier; it just unlocks the external-client flow and the billing and handoff that go with it. ## What the partner flag turns on Being a partner adds three capabilities. Your own internal work carries on exactly as before. 1. *External-client workspaces.* Admins can mark a new workspace as serving an external client, not your own team. 2. *Separate client billing.* Each external-client workspace bills on its own, instead of drawing on your organisation's pooled seats. 3. *Handoff.* A finished engagement can be transferred to the client as an independent organisation. ## External-client workspaces You create one like any other workspace, but you tell dembrane it's for a client and supply who really owns the data: the *data-owner organisation name* (e.g. "City of Haarlem"), the *data-owner email* (the client contact), and a *partner agreement* checkbox confirming you've agreed terms. dembrane records when you accepted it. dembrane then bills the workspace on its own, auto-invites the data owner as a free [observer](#observer-and-external) so they can watch at no cost, and lets you put the client's (or your own) logo on the participant portal. Each client's conversations, billing, and branding stay in their own box. For the walkthrough, see [external-client workspaces](../users/host-partner/external-client-workspaces.md). > [!TIP] > Internal vs external is the most important distinction in partner work. Internal > workspaces share your pooled billing and branding; external ones name a data owner, bill > separately, allow free observers, and support white labelling. The full picture is on > [data ownership & compliance](./data-ownership-and-compliance.md). ## Observer and external Two [workspace roles](./roles-and-permissions.md) carry client engagements. Both show in grey to signal they're outside collaborators. - *Observer* is free and read-only. They can view projects, read conversations, and view reports - nothing else. Observers cost nothing, only exist in external-client workspaces (internal workspaces reject them), and the data owner is invited as one automatically. - *External* is a *paid* seat for an outside collaborator who needs to do real work: read conversations, edit projects, use [chat](./chat-and-ask.md), and generate (not publish) [reports](./reports.md). They can't create or delete projects, capture, or invite. To turn an observer into a paid external - say the client wants to generate their own reports - an admin just changes their role. For day-to-day work with both, see [observer & external collaborators](../users/host-partner/observer-and-external-collaborators.md). ## Moving and handing off work - *Move projects.* You can move a project, or several at once, between workspaces - handy for reorganising as a programme grows or separating one client's work from another's. - *Handoff.* When an engagement is done, the workspace can be *transferred* so the client owns it as an independent organisation, no longer billed through you. Handoff is done with staff help. > [!IMPORTANT] > Handoff changes who owns and pays for a workspace. Agree the timing with your client and > your dembrane contact first - once handed off, your organisation no longer administers > it. The full procedure is on [data ownership & handoff](../users/host-partner/data-ownership-and-handoff.md). ## Referrals When you bring dembrane a client who later signs up, that can be tracked. The *referral ledger* records the relationship and any agreed terms - a kickback percentage, a client discount, a cap, an expiry. dembrane maintains it; you don't manage it yourself. Set the terms with your dembrane contact, and see [referrals](../users/host-partner/referrals.md) for the overview. ## Related - [Data ownership & compliance](./data-ownership-and-compliance.md) - internal vs external, data owner, white labelling, GDPR posture. - [Roles & permissions](./roles-and-permissions.md) - the full capability matrix, including observer and external. - [Tiers & billing](./tiers-and-billing.md) - per-seat pricing and what observers cost (nothing). - [Partner guides](../users/host-partner/index.md) - everything above, from a partner host's point of view. --- # Data ownership & compliance Every workspace belongs to someone, and dembrane is explicit about *who*. A workspace is either *internal* - your organisation's own work, on your billing and branding - or *external* - work you run for a named client, billed separately, with the client recorded as the *data owner*. That one choice shapes billing, branding, and who can see what. You'll reach for this when you decide whether a new workspace is yours or a client's, when a client asks "where is our data and who can access it?", or when a compliance officer wants to know dembrane's GDPR stance. The internal/external choice is made by a workspace [admin or owner](./roles-and-permissions.md) when creating or editing a workspace. ## Internal vs external | | Internal workspace | External workspace | |---|---|---| | Billing | Shares the organisation's *pooled* seats | Its *own* workspace-scoped account | | Branding | Inherits the organisation's logo | Can be *white-labelled* per workspace | | Data owner | The organisation itself | A *named external client* (org name + email) | | Free observers | Not allowed | *Allowed* - the data owner is auto-invited as one | Internal is the default and the right choice for your own team. External is for work you run for someone else - see [the partner program](./partner-program.md), which is built around external-client workspaces. ## The data owner On an external workspace, dembrane records the *data-owner organisation name* (e.g. "Provincie Utrecht") and the *data-owner email* - the specific person who owns the conversations. When that person logs in and their email matches, the workspace shows a "this is yours" marker in their list, without exposing anyone else's details. It also drives the automatic free-observer invite, so the data owner can watch progress at no cost. > [!NOTE] > The data owner is the *client* who owns the conversations, not the host who runs the > sessions. A partner agency facilitates; the client owns. Keeping those separate is the > whole point of an external workspace. When you create an external-client workspace you also confirm a *partner agreement* - a checkbox stating you and the client have agreed terms for handling their data. dembrane stores the moment you accepted it: a lightweight, auditable record that the relationship was acknowledged before any conversations were collected. ## White labelling White labelling puts a client's (or your own) logo on the [participant portal](./portal-and-participant-experience.md) instead of dembrane's. It's *external-workspace-only*, on [Changemaker](./tiers-and-billing.md) and above. For a partner, each engagement can carry the client's identity - the people you record see the client's brand, not yours and not dembrane's. ## EU & GDPR posture dembrane is built for European, privacy-sensitive work: - *GDPR.* Designed to be GDPR-compliant - lawful basis is captured per project, and personal data can be removed (see *anonymisation* below). - *ISO 27001.* dembrane operates to ISO 27001 information-security practices. - *EU co-funded.* dembrane's development has been co-funded within the EU. - *EU hosting.* Built-in analysis runs on EU-hosted models; transcription is handled securely. Self-hosters can pin everything to EU regions - see [self-hosting](../users/developer-external/self-hosting.md). > [!IMPORTANT] > For the authoritative legal documents - the privacy statement, terms, and the data > processing agreement - see dembrane's legal pages and privacy statements (linked from the > dashboard). This page describes posture, not legal terms. ### Anonymisation dembrane can *anonymise transcripts* so personal data is removed during processing. When enabled per project in the [portal editor](./portal-editor.md), the pipeline redacts identifiable information as it cleans up the text, and each conversation shows its anonymisation status. This matters when you collect from members of the public who shouldn't be re-identifiable in the analysis. The redaction mechanics are under [transcription](./transcription.md). ### Guardian - the EU-sovereign stack (coming soon) The *Guardian* tier adds a fully *EU-sovereign* stack: hosting and language models that sit entirely within European jurisdiction and aren't exposed to extraterritorial data requests. It's aimed at the most sensitive work, where even EU-hosted-but-US-owned infrastructure isn't acceptable. Guardian is *coming soon*, gated on the sovereign stack shipping - see [tiers & billing](./tiers-and-billing.md) for where it sits. ## Related - [The partner program](./partner-program.md) - external-client workspaces in practice. - [Tiers & billing](./tiers-and-billing.md) - where white labelling (Changemaker+) and the Guardian sovereign stack live. - [Transcription](./transcription.md) - secure, multilingual transcription and PII redaction. - [Roles & permissions](./roles-and-permissions.md) - who can change data-ownership settings. --- # The admin panel The admin panel is where you watch the health of every account, change tiers, approve upgrades, issue invoices, grant trials, and run trainings - everything a customer can't do to their own account. This page is the map: how to get in, what each section is for, and the *kebab menu* you'll use over and over. You reach it with a staff account - see [getting in](./index.md#getting-in). A few of the most sensitive actions need extra permission on top of that; where one applies, that action's page says so. ## Getting in You reach the panel from the dashboard, the same way you'd reach your own settings - you just see more. If it isn't there, your account isn't set up as staff yet; ask whoever manages staff access. ## The sections ### Usage & billing The master rollup: every billing account and its workspaces, what they use, what they pay, and what they're forecast to pay. It carries the revenue classification (trial / managed / comped / paying), the MRR forecast, admin contacts, CSV export, and a 12-month lookback. → [Usage & billing rollup](./usage-and-billing-rollup.md). ### At-risk The rollup pre-triaged for outreach: pilot hard-blocks, at-cap, approaching-cap, and recently-downgraded accounts, sorted with the most urgent on top. → [Account health & at-risk](./at-risk-and-account-health.md). ### Payments The Mollie side of billing: transactions taken, their statuses, and deep links into Mollie to chase a failed or pending payment. Managed (offline) invoices reconcile against real money here. → [Managed & offline billing](./managed-and-offline-billing.md). ### Training The compliance-training admin: the catalogue, scheduling sessions, completing them (which grants every attendee a one-year licence), and the roster. → [Trainings & licences](./trainings-and-licences.md). > [!TIP] > Two jobs don't have their own tab but run through the panel: *upgrade requests* (the > approve/deny queue - see [upgrade requests](./upgrade-requests.md)) and *partner ops* (the > toggle, referral ledger, external-led-orgs signal - see > [partner administration](./partner-administration.md)). ## The kebab-action model Most of what you *do* happens through a *kebab menu* - the three-dot (⋮) button next to a row. The rollup and at-risk lists are tables of accounts and workspaces; each row's kebab opens the actions you can take against that account or workspace. *Workspace actions* (per workspace row): - *Change tier* - needs extra staff permission. See [discounts, trials & tiers](./discounts-trials-and-tiers.md#changing-a-tier). - *Change admin* - for when the named admin is unreachable. See [discounts, trials & tiers](./discounts-trials-and-tiers.md#changing-the-admin). - *Reset usage* - with a *reason*. See [discounts, trials & tiers](./discounts-trials-and-tiers.md#resetting-usage). - *Discount* - scholarship / staff discount / trial, as a percentage. See [discounts, trials & tiers](./discounts-trials-and-tiers.md#discounts). *Account actions* (per billing account): - *Grant reverse trial* - one month of Changemaker, auto-reverting. See [discounts, trials & tiers](./discounts-trials-and-tiers.md#granting-a-reverse-trial). - *Discount* - the canonical place to set one is the account level. See [discounts, trials & tiers](./discounts-trials-and-tiers.md#discounts). - *Set managed / assign account manager / issue payment link / issue invoice / mark paid* - the whole offline-billing flow. See [managed & offline billing](./managed-and-offline-billing.md). *Organisation actions*: - *Partner toggle* - see [partner administration](./partner-administration.md#the-partner-toggle). > [!WARNING] > Kebab actions take effect immediately and most are visible to the customer (a tier change, a > reset, a discount on their next invoice). There's no draft state. Read the action's page > first, and use the *reason* field where one is offered - it's the audit trail. ## A typical visit 1. Open *Usage & billing*, pick the month, scan revenue and the MRR forecast. 2. Jump to *At-risk* to see who needs a nudge; use each row's kebab to reset usage, apply a discount, or grab the [admin contact](./usage-and-billing-rollup.md#admin-contacts) to email. 3. Clear the *upgrade-request* queue - approve the genuine ones, deny the rest. 4. If finance needs it, open *Payments* to reconcile a managed invoice or chase a failed Mollie charge. 5. If you ran a training, open *Training* and complete the session to grant licences. ## Related - [Staff overview](./index.md) - what the panel is and how to get in. - [Usage & billing rollup](./usage-and-billing-rollup.md) - the master table you start from. - [Account health & at-risk](./at-risk-and-account-health.md) - the pre-triaged outreach list. - [Tiers & billing](../../features/tiers-and-billing.md) - the plans you change from here. - [Roles & permissions](../../features/roles-and-permissions.md) - the customer roles the rollup shows. - [Roles & policies in code](../developer-internal/roles-and-policies.md#staff-policies) - the gate, staff policies, and admin API, for engineers. --- # Usage & billing rollup The billing rollup shows every billing account on dembrane, broken down by workspace, with what each is using and what each pays. It's the panel's home view and answers the standing questions: who's paying, who's on a trial, what's our recurring revenue, where is it forecast to go. Any [staff](./index.md#getting-in) account can open and export it. The *actions* you reach from each row - change tier, apply a discount, issue an invoice - have their own gating; see [the kebab-action model](./admin-panel-overview.md#the-kebab-action-model). ## What's in a row The rollup nests two levels: - *Per billing account* - the billing unit. Usually organisation-scoped (one pooled account across internal workspaces); for [external-client](../../features/partner-program.md) work it's workspace-scoped. The account row carries the revenue class, the MRR figure, and the [admin contact](#admin-contacts). - *Per workspace* - under each account, the workspaces that draw on it, each with its own [tier](../../features/tiers-and-billing.md), seat count, and usage. This mirrors how [billing is organised](../../features/tiers-and-billing.md#how-billing-is-organised): seats and money attach to the account; usage happens in the workspaces. ## Revenue classes Every account is sorted into a *revenue class* so you can tell real money from everything else: | Class | What it means | |---|---| | *paying* | A genuine paying customer - Mollie subscription or a paid managed invoice. This is the money. | | *trial* | On a [reverse trial](./discounts-trials-and-tiers.md#granting-a-reverse-trial) or otherwise trialling - revenue *if* they convert, not yet. | | *managed* | Billed offline by bank transfer rather than self-serve Mollie. See [managed & offline billing](./managed-and-offline-billing.md). | | *comped* | Complimentary - a [discount](./discounts-trials-and-tiers.md#discounts) brings them to no or reduced cost. Real usage, intentionally not (fully) billed. | > [!TIP] > The classes are the quickest sanity check on the business. Trials that never become paying > are a conversion problem; a growing comped column is generosity worth reviewing. Use the > [status filter](#filters) to isolate one class. ## MRR forecast Each account contributes to a *monthly recurring revenue (MRR) forecast* - what dembrane expects to earn from it monthly, derived from its tier, seats, and billing cadence. The forecast normalises different billing cadences to a comparable monthly figure. The rollup totals it across the accounts in view, so a [filter](#filters) re-totals the forecast for that slice. > [!NOTE] > The forecast is a forecast, not booked revenue. Unconverted trials and unpaid managed > invoices are potential, not banked. Cross-check the > [payments rollup](./managed-and-offline-billing.md#the-payments-rollup) for what's actually arrived. ## Admin contacts Each account row surfaces its *admin contact* - the person to email. That's what turns the rollup into an outreach tool: you spot an at-risk or expiring account and already have the name and address, without digging through the member list. If the listed admin is unreachable, that's the case [change admin](./discounts-trials-and-tiers.md#changing-the-admin) exists for. ## The 12-month lookback Use the month lookback to step back through the last 12 months. The current month is the default, then last month, and so on. Use it to see what an account looked like before a downgrade, compare months, or pull a historical month for a finance reconciliation. ## Filters The rollup is large, so filter to the slice you need: - *Search* - by account or workspace name (and admin contact), to jump to one customer. - *Tier* - Free, Innovator, Changemaker, or Guardian only. Handy for "who's still on Free and using a lot?" - *Status / revenue class* - isolate paying, trial, managed, or comped. Filters re-total the [MRR forecast](#mrr-forecast) for the visible set, so they double as quick aggregates. ## CSV export Any view - filtered or not, this month or a lookback month - exports to *CSV*: a finance hand-off, a revenue-class slide, or a spreadsheet pivot beyond what the table shows. The export reflects the current filters and month, so set those first. ## How you'd use it 1. Open the rollup on the current month. 2. Glance at the totals - MRR forecast, the split across revenue classes. 3. Filter to *paying* for banked recurring revenue; to *trial* for the conversion pipeline. 4. Search any account you've been asked about; read its tier, seats, usage, and admin contact. 5. From a row's [kebab](./admin-panel-overview.md#the-kebab-action-model), take whatever action the situation needs - or note the contact and reach out. 6. Export to CSV if someone downstream needs the numbers. ## Related - [The admin panel](./admin-panel-overview.md) - where the rollup sits and the kebab actions it offers. - [Account health & at-risk](./at-risk-and-account-health.md) - the rollup pre-triaged into who needs attention. - [Managed & offline billing](./managed-and-offline-billing.md) - what "managed" means and the payments rollup behind real money. - [Discounts, trials & tiers](./discounts-trials-and-tiers.md) - what "comped" and "trial" mean and how to set them. - [Tiers & billing](../../features/tiers-and-billing.md) - the plans, seats and billing accounts behind the forecast. --- # Account health & at-risk The at-risk list is the billing rollup pre-triaged: just the accounts that need a human right now - hit a wall, about to, or just lost capacity - sorted with the most urgent on top. It's the staff "needs attention" inbox. Any [staff](./index.md#getting-in) account can read it. The remedies you reach from it - [resetting usage](./discounts-trials-and-tiers.md#resetting-usage), a [discount](./discounts-trials-and-tiers.md#discounts), a [tier change](./discounts-trials-and-tiers.md#changing-a-tier) - carry their own gating. ## The categories Accounts land on the list for one of four reasons, in descending urgency. ### Pilot hard-block The most urgent. A *pilot* account that has hit a hard block and is now *stopped*, not merely warned - recording or other gated activity is blocked. These are live problems: someone is trying to use dembrane and can't. > [!IMPORTANT] > Pilot hard-blocks are the only category where the customer is actively blocked rather than > nudged. Treat them as time-sensitive. ### At-cap The account has reached its limit - most commonly the one-hour recording cap on [Free](../../features/tiers-and-billing.md#free), the only tier with an hour cap. Often the right move is an upgrade conversation, or a temporary [usage reset](./discounts-trials-and-tiers.md#resetting-usage) or [trial](./discounts-trials-and-tiers.md#granting-a-reverse-trial) to unblock them while it happens. ### Approaching-cap Not at the limit yet, but close at the current rate. The *best* time to reach out - before frustration, while the upgrade is a suggestion rather than a rescue. ### Recently-downgraded An account that dropped a tier - a churn signal. Something changed: budget, a champion left, the value wasn't landing. Worth a check-in, and sometimes a [discount](./discounts-trials-and-tiers.md#discounts) to keep them. > [!TIP] > Severity ordering means you can work the list top-down: clear pilot hard-blocks first, then > at-cap, approaching-cap, downgrades. You rarely need to read past where your time runs out. ## The admin-logins proxy The list also shows *admin logins* - how recently and often an account's admin has logged in, a cheap signal of whether anyone's actually using dembrane. Read it alongside the category: - *Approaching-cap + frequent logins* → an engaged account growing into a paid tier. A warm upgrade conversation. - *At-cap + no recent logins* → they hit the wall and walked away. Re-engagement, not upsell. - *Recently-downgraded + healthy logins* → they're staying, just spending less. Worth understanding what changed. ## The outreach For each row: 1. *Read the category and login proxy* to understand the kind of problem. 2. *Grab the [admin contact](./usage-and-billing-rollup.md#admin-contacts)* to write to. If unreachable, that's a [change-admin](./discounts-trials-and-tiers.md#changing-the-admin) case. 3. *Pick the remedy* from the row's [kebab](./admin-panel-overview.md#the-kebab-action-model): - Blocked or at-cap and you want to unblock now → [reset usage](./discounts-trials-and-tiers.md#resetting-usage) (with a reason) or a [reverse trial](./discounts-trials-and-tiers.md#granting-a-reverse-trial). - Genuine upgrade → help them, or [change the tier](./discounts-trials-and-tiers.md#changing-a-tier) once they agree. - Price is the blocker → a [discount](./discounts-trials-and-tiers.md#discounts) to keep a good account. 4. *Note the reason* where the action asks for one - it's the audit trail. > [!WARNING] > Resetting usage or granting a trial unblocks the customer immediately and is visible to > them. Don't reset silently to make a number look better - use the reason field and pair it > with a real conversation, or you'll be back here next month. ## Related - [Usage & billing rollup](./usage-and-billing-rollup.md) - the full list this view triages from, and where admin contacts come from. - [Discounts, trials & tiers](./discounts-trials-and-tiers.md) - every remedy: reset usage, trials, discounts, tier changes. - [The admin panel](./admin-panel-overview.md) - the kebab-action model behind the remedies. - [Tiers & billing](../../features/tiers-and-billing.md) - the Free hour cap that puts accounts at-cap. --- # Upgrade requests An *upgrade request* is how a customer who can't change their own plan asks dembrane to do it. A [member](../../features/roles-and-permissions.md) without billing rights doesn't pay the bill, so when they reach for a higher tier or a new workspace they submit a request - and it lands in a staff queue where you approve or deny it. Reading and actioning the queue is [staff](./index.md#getting-in) work. Approving a request that changes a tier performs a [tier change](./discounts-trials-and-tiers.md#changing-a-tier), so it needs extra staff permission. The customer side - who can submit, and why - is on [tiers & billing](../../features/tiers-and-billing.md#requesting-an-upgrade). ## The lifecycle 1. *Submit* - a customer with `upgrade:request` raises it from the dashboard. Stored in the `workspace_request` collection with its kind, target workspace, and who asked. 2. *List* - it appears in the queue with the requester, workspace, kind, and when it came in. 3. *Approve* - for a tier upgrade, that bumps the workspace's tier; for a new workspace, it clears the way for it to exist on the requested footing. 4. *Deny* - decline it, with a note to the requester about why. > [!TIP] > Approving a request and changing a tier from the > [kebab](./admin-panel-overview.md#the-kebab-action-model) reach the same end. Use the queue > when the customer *asked* (it closes the loop for them); use a direct tier change when > *you* initiate, e.g. after a renewal call. ## The two kinds - `new_workspace` - the customer wants a workspace they can't create under their current plan. On [Free](../../features/tiers-and-billing.md#free), extra workspaces are gated, so this is the route to one. - `tier_upgrade` - the customer wants their existing workspace moved up (for example, Free → [Changemaker](../../features/tiers-and-billing.md)). Read the kind first: it tells you whether you're approving a new thing or changing an existing one, and which workspace is affected. ## Notifications and the daily digest Requests generate [notifications](../../features/notifications.md), and the emails are batched: - *The first five in a 24-hour window* are emailed individually, so a low-volume queue reaches you in real time. - *After that*, further requests roll into a *daily digest* at *09:00 UTC*, so a busy day doesn't flood your inbox. > [!NOTE] > That's why you might get a handful of individual emails early and a single digest later. > The in-app [notifications](../../features/notifications.md) always show the full queue > regardless of how the emails batched. ## The expiry and prewarning crons Two scheduled jobs run alongside the queue so time-limited grants don't overstay: - *Tier-expiry cron* - when a time-limited tier (usually a [reverse trial](./discounts-trials-and-tiers.md#granting-a-reverse-trial)) reaches its end date, it reverts the workspace. No manual downgrade needed. - *3-day prewarning cron* - three days before an expiry, a warning goes out so the customer (and you) get a heads-up before capacity changes. So a trial granted today reverts on its own in a month, with a warning three days out - see [granting a reverse trial](./discounts-trials-and-tiers.md#granting-a-reverse-trial). > [!IMPORTANT] > Because expiries auto-revert, don't rely on a trial as a permanent discount. If an account > genuinely shouldn't pay full price, set a proper > [discount](./discounts-trials-and-tiers.md#discounts) instead - it doesn't expire out from > under them. ## Related - [Notifications](../../features/notifications.md) - how requests notify you and how the digest batching works. - [Discounts, trials & tiers](./discounts-trials-and-tiers.md) - what approving actually does, plus trials and the expiry crons. - [Tiers & billing](../../features/tiers-and-billing.md#requesting-an-upgrade) - the customer side: who can request and why. - [The admin panel](./admin-panel-overview.md) - where the queue lives and the kebab actions beside it. --- # Managed & offline billing Workspaces that already hold a subscription pay through [Mollie](../../features/tiers-and-billing.md#payments) - card, automatic renewal, no human in the loop; new workspaces contact dembrane to arrange billing. Plenty of customers need neither: public-sector bodies, larger organisations, anyone who needs a formal invoice and pays by bank transfer. For them, dembrane runs *managed (offline) billing* - staff issue the invoice, the customer pays out-of-band, staff record the payment. This page covers that flow plus the *payments rollup* that reconciles it against real money. It's [staff](./index.md#getting-in) work. Issuing invoices and marking them paid touches real money - treat it like anything in finance. Customers can't see or perform any of it; from their side they receive an invoice and pay it. ## Setting an account to managed Mark a billing account *managed* to flip it out of the self-serve Mollie path. It now classes as [managed in the rollup](./usage-and-billing-rollup.md#revenue-classes), and the invoice/payment-link actions become available against it. > [!NOTE] > Managed is a billing *mode*, not a tier. A managed account can be on any > [tier](../../features/tiers-and-billing.md). It changes *how they pay*, not *what they have*. ## Account managers A managed account usually has a named *account manager* - a dembrane person who owns the commercial relationship. *Assign* or *clear* it from the account's actions; the address must be a dembrane one (`@dembrane.com`). Paired with the [admin contact](./usage-and-billing-rollup.md#admin-contacts) on the rollup, you have both ends: who at dembrane owns it, and who at the customer to talk to. ## Issuing a payment link For a managed account that *could* pay online but needs a nudge, *issue a payment link* - a one-off link the customer follows to pay. The middle ground between full self-serve and a formal invoice: you control when it goes out, but they still pay through the normal rails. ## Issuing an invoice For the formal route, *issue an invoice* - the document a finance department needs to release a bank transfer. It supports: - *VAT* - the applicable tax, so the customer's finance team can book it. - *E-invoice* - a structured electronic invoice for customers (often public sector) whose systems require it rather than a PDF. Issue it against the managed account at the agreed amount and tier, with the right VAT treatment, and send it. > [!IMPORTANT] > An issued invoice is unpaid until you say otherwise, and issuing it grants nothing on its > own - it's a request for money. Combine it with the agreed > [tier](./discounts-trials-and-tiers.md#changing-a-tier) so the customer has what they're > paying for, and [mark it paid](#marking-an-invoice-paid) when the money lands. ## Marking an invoice paid When the bank transfer arrives, *mark the invoice paid*. This is the out-of-band reconciliation step: dembrane can't know a transfer landed in the company bank account, so a human records it. Marking it paid moves the account into the *paid* state - what turns a managed account into genuine [paying](./usage-and-billing-rollup.md#revenue-classes) revenue in the rollup. > [!WARNING] > Only mark an invoice paid once you have confirmation the money arrived. This is the step the > revenue numbers trust - marking unpaid invoices as paid inflates the > [rollup](./usage-and-billing-rollup.md) and the > [MRR forecast](./usage-and-billing-rollup.md#mrr-forecast) with money that isn't there. ## The payments rollup The payments rollup is the view of what's happened on the *Mollie* side: transactions and their statuses, with deep links into Mollie to open any transaction at source. Use it to: - Confirm a self-serve charge went through, or find out why it didn't. - Chase a failed or pending Mollie payment via the deep link. - Reconcile what the [billing rollup](./usage-and-billing-rollup.md) forecasts against what Mollie actually collected. > [!TIP] > The two views answer different questions. The > [billing rollup](./usage-and-billing-rollup.md) is "what *should* each account pay?"; the > payments rollup is "what *did* arrive, through Mollie?". A gap is usually an unpaid managed > invoice or a failed Mollie charge. ## The managed flow, end to end 1. *Set the account managed* - flip it out of self-serve. 2. *Assign an account manager* (`@dembrane.com`). 3. *Issue the invoice* with the right VAT and, if needed, as an e-invoice. 4. The customer *pays by bank transfer* out-of-band. 5. *Mark the invoice paid* once the money is confirmed. 6. Reconcile in the [payments rollup](#the-payments-rollup) and check the account now reads as [paying](./usage-and-billing-rollup.md#revenue-classes). ## Related - [Usage & billing rollup](./usage-and-billing-rollup.md) - where managed and paid accounts show up, and the revenue classes. - [Discounts, trials & tiers](./discounts-trials-and-tiers.md) - set the tier the invoice bills for. - [The admin panel](./admin-panel-overview.md) - the kebab actions for managed billing. - [Tiers & billing](../../features/tiers-and-billing.md#payments) - Mollie and where managed invoicing fits. --- # Discounts, trials & tiers These are the direct levers on a customer's account: knock the price down with a *discount*, hand them a month of paid capacity with a *reverse trial*, *change the tier* outright, *change the admin* when the named one is unreachable, and *reset usage* to unblock someone. They're the remedies behind most [at-risk](./at-risk-and-account-health.md) outreach and renewal conversations. All of it is [staff](./index.md#getting-in) work; changing a tier additionally needs extra staff permission. Each action hangs off the [kebab](./admin-panel-overview.md#the-kebab-action-model) on an account or workspace row. ## Discounts A *discount* reduces what an account pays, as a percentage off - the canonical remedy for "this account should pay less". Three kinds: | Kind | When you'd use it | |---|---| | *scholarship* | A non-profit, community group, or cause you want to support at a reduced or zero price. | | *staff_discount* | A dembrane-staff-adjacent account that gets a price break. | | *trial* | A discount tied to a trial arrangement. | 100% is effectively free (this makes an account [comped](./usage-and-billing-rollup.md#revenue-classes) in the rollup); 50% is half-price. > [!NOTE] > Set discounts at the *billing account* level - that's where billing attaches. There's also a > per-workspace action for when a single workspace needs its own treatment. When in doubt, > discount the account. > [!TIP] > Prefer a discount over a permanent trial. A [reverse trial](#granting-a-reverse-trial) > *expires*. If an account genuinely shouldn't pay full price long term, a discount is the > durable answer. ## Granting a reverse trial A *reverse trial* drops a Free (or lower) account into *Changemaker for one month* - the full paid experience (built-in analysis, unlimited hours) without paying. The key word is *reverse*: it auto-reverts. A [cron](./upgrade-requests.md#the-expiry-and-prewarning-crons) downgrades the account at the end of the month, with a 3-day prewarning. You don't have to remember to take it away. Use it when an [at-cap](./at-risk-and-account-health.md#at-cap) Free account needs unblocking *and* you want to show paid value, or in a sales conversation to let a prospect feel Changemaker before deciding. > [!IMPORTANT] > Because it reverts automatically, never use a reverse trial as a stand-in for a discount. > It's a time-boxed taste. For anything lasting, use a [discount](#discounts). ## Changing a tier To move a workspace up or down directly. Needs extra staff permission. You'd change a tier when: - A customer agreed to upgrade and you're completing it (or [approving their request](./upgrade-requests.md)). - You're correcting a tier after a [managed invoice](./managed-and-offline-billing.md#issuing-an-invoice) is paid. - You're downgrading a lapsed account. The tiers themselves - Free, Innovator, Changemaker, Guardian, and what each unlocks - are on [tiers & billing](../../features/tiers-and-billing.md#the-four-tiers). > [!WARNING] > A tier change is immediate and visible. Downgrading removes capabilities the customer may > rely on (analysis, extra workspaces, white labelling). Make sure billing and the customer > are aligned, especially downward. ## Changing the admin When a workspace's named admin is unreachable - left the organisation, email bounces, nobody else has access - reassign administration to a different person. This is an unreachable-admin recovery tool, not a routine one. It exists so an account isn't stranded because its only admin vanished. > [!NOTE] > Confirm the customer's request before reassigning - you're handing control of their > workspace to a different person. Pair it with the > [admin contact](./usage-and-billing-rollup.md#admin-contacts) so you know who the legitimate > new owner should be. ## Resetting usage *Reset usage* clears an account's consumed usage - most usefully the [Free hour cap](../../features/tiers-and-billing.md#free) - so an [at-cap](./at-risk-and-account-health.md#at-cap) customer can carry on. It *requires a reason*. The reason is the audit trail for *why* this account got extra capacity - "founder demo", "billing error", "goodwill while resolving an upgrade". > [!WARNING] > Don't reset usage to make a dashboard look healthier. It unblocks the customer immediately > and erases the signal that put them on the [at-risk list](./at-risk-and-account-health.md). > Fill in a truthful reason and pair the reset with a real upgrade conversation, or the same > account is back at-cap next month. ## Choosing the right lever | Situation | Reach for | |---|---| | Should pay less, long term | [Discount](#discounts) (scholarship / staff) | | Show paid value, time-boxed | [Reverse trial](#granting-a-reverse-trial) | | Agreed upgrade / correction | [Change tier](#changing-a-tier) | | Named admin vanished | [Change admin](#changing-the-admin) | | Unblock an at-cap account now | [Reset usage](#resetting-usage) (with reason) | ## Related - [Account health & at-risk](./at-risk-and-account-health.md) - where you decide which lever an account needs. - [Upgrade requests](./upgrade-requests.md) - approving a request, and the expiry/prewarning crons behind reverse trials. - [Managed & offline billing](./managed-and-offline-billing.md) - set the tier an invoice bills for. - [The admin panel](./admin-panel-overview.md) - the kebab-action model these hang off. - [Tiers & billing](../../features/tiers-and-billing.md) - the tiers you change and what each includes. --- # Partner administration The [partner program](../../features/partner-program.md) lets an agency run dembrane on behalf of external clients. It's self-serve for the partner *once* their organisation is marked as a partner - but that mark, and a few commercial and operational levers around it, only staff can pull: the *partner toggle*, the *referral ledger*, the *external-led-orgs* signal, and *workspace handoff*. It's [staff](./index.md#getting-in) work; handoff additionally needs extra staff permission. Partners can't toggle any of this themselves - that's the point of staff-gating it. ## The partner toggle Every organisation has a partner flag, off by default. Turning it on is the single gate that opens the partner program for that organisation. On, it lets that organisation's workspace admins create [external-client workspaces](../../features/partner-program.md#external-client-workspaces) - which carry their own billing account, name a data owner, allow [free observers](../../features/roles-and-permissions.md), and support white labelling. Internal work is unchanged; the toggle only *adds* the partner capability. > [!IMPORTANT] > Only flip the partner flag on once a partner agreement is in place. It changes how the > organisation can bill and hand off other people's data. Confirm with whoever owns the > partner relationship first. The customer-facing view of what this unlocks is on the [partner program](../../features/partner-program.md) page; route partner hosts there when they ask "what can I now do?". ## The referral ledger Partners bring clients, often with agreed commercial terms. The *referral ledger* is where those terms live. Each entry records: - *Kickback %* - what the partner earns on a referred client. - *Discount %* - any discount the referred client gets. - *EUR cap* - a ceiling in euros on the arrangement. - *Expiry* - when the deal lapses. It's staff-maintained; partners don't edit it. Read it to reconcile what a partner is owed, check a referred client's discount, and see when an arrangement ends. > [!NOTE] > The ledger is the mechanism; the deals are agreed with the partner by whoever owns the > commercial relationship. If a number looks wrong, check the agreement before editing. ## External-led orgs - the conversion signal The *external-led orgs* list surfaces organisations that look like they're being led from outside the partner - a partner's external client that has started behaving like an independent account. When a client a partner brought in starts driving their own usage, inviting their own people, and acting like an owner rather than an observer, they're a candidate to convert to their own direct dembrane account. Read the list as a pipeline of clients ready to graduate from partner-hosted to independent. > [!TIP] > Pair it with the [referral ledger](#the-referral-ledger): a client showing up as > external-led, with a referral arrangement near its [cap or expiry](#the-referral-ledger), is > a clear prompt for a "ready to take this over yourself?" conversation - and to settle the > partner's kickback. ## Workspace transfer and handoff When an engagement ends, a partner often hands the workspace to the client so the client owns it as an independent organisation, billed directly. That transfer is *handoff*, which needs extra staff permission - so staff usually perform or assist it. Handoff changes who owns and pays for a workspace, so: - Confirm timing with *both* the partner and the client before transferring. - Make sure the client side is ready - they become the owners, billed directly. - After handoff, the partner organisation no longer administers the workspace. The same machinery covers project moves and bulk moves between workspaces; the customer-facing detail is on the [partner program](../../features/partner-program.md#moving-and-handing-off-work) page. > [!WARNING] > Handoff is not easily undone - once a workspace is transferred, the partner loses > administrative access. Treat it as a one-way door and line everything up first. ## Related - [The partner program](../../features/partner-program.md) - the full customer-facing picture of what the toggle unlocks. - [Roles & permissions](../../features/roles-and-permissions.md) - the observer and external roles partners use. - [Usage & billing rollup](./usage-and-billing-rollup.md) - where external-client billing accounts show up. - [The admin panel](./admin-panel-overview.md) - the partner toggle as a kebab action. - [Discounts, trials & tiers](./discounts-trials-and-tiers.md) - discounts you might apply alongside a referral deal. --- # Trainings & licences dembrane runs *trainings* for people deploying it in high-risk or regulated settings - the sessions that make sure facilitators can collect, handle, and analyse sensitive conversations responsibly. Completing a training grants each attendee a *one-year licence*, the record that they've been trained. This page is the staff side: the catalogue, scheduling sessions, completing them to issue licences, and managing the roster. It's the *Training* section of the [admin panel](./admin-panel-overview.md#the-sections). The customer-facing view is on [trainings](../../features/trainings.md). ## What trainings are for These aren't product tutorials - those live in the [help resources](../../features/index.md). Trainings here are *compliance trainings*: structured sessions for people running dembrane where the stakes are high (sensitive cohorts, regulated processes, public consultations that demand careful data handling). The one-year licence is the evidence someone completed one. ## The catalogue The catalogue is the set of trainings dembrane offers. You *create* and *update* trainings here. Each has a *mode*: - *online* - delivered remotely. - *in_person* - delivered face to face. - *flex* - either, as the situation needs. The catalogue is the template layer: a training defines *what* the session is. A scheduled session is an *instance* of one, with a date and a roster. ## Creating and scheduling a session To run a training, pick or create the training in the catalogue and *schedule* a session - set its date and mode, then build the *roster* of attendees. The roster is the list licences are issued against when you complete the session, so get the right people on it first. > [!TIP] > Build the roster as registrations come in. Licences aren't granted until you > [complete](#completing-a-session--granting-licences) the session, so a last-minute change > before completion is no problem. ## Completing a session → granting licences When the session has happened, *complete* it. Completion grants a one-year `training_license` to every person on the roster. That licence: - Lasts one year from when it's granted. - Is recorded per user, so each attendee carries their own. - Is the record other parts of dembrane can check to confirm someone's been trained. > [!IMPORTANT] > Completing is the moment licences are issued. Get the roster right *before* you complete - > far cleaner than issuing to the wrong list and then > [revoking](#editing-and-revoking-licences). If someone didn't attend, take them off first. ## The roster The roster is the attendee list for a session - who's expected, and (after completion) who was granted a licence. Add and remove people before completion; read it afterwards as the record of who the session licensed. ## Editing and revoking licences You can *edit* a licence (correct a detail) or *revoke* it (remove it) when: - The wrong person was granted one. - Someone withdrew or shouldn't hold a current licence. - A correction is needed after the fact. Revoking removes the licence; the person no longer counts as trained until granted a new one (by completing another session). > [!NOTE] > A licence expires after a year on its own - you don't have to revoke it to end it. Revoke is > for when it shouldn't run its full term. To renew someone, put them on the roster of a fresh > session and complete it. ## The training flow, end to end 1. *Create or pick* the training in the [catalogue](#the-catalogue), with its mode. 2. *Schedule* a session - date and mode. 3. *Build the roster* of attendees. 4. Run the session. 5. *Complete* it → every roster member gets a [one-year licence](#completing-a-session--granting-licences). 6. *Edit or revoke* any licence that needs correcting afterwards. ## Related - [Trainings](../../features/trainings.md) - the customer-facing view: what a trained user sees about their licence. - [The admin panel](./admin-panel-overview.md) - the Training section and how to reach it. - [Staff overview](./index.md) - the admin gate that lets you run trainings at all. - [Roles & permissions](../../features/roles-and-permissions.md) - how trained users fit the wider role model. --- # Staff support access Sometimes a customer hits a problem that is faster to fix from inside their own workspace than to debug over email. Staff support access lets a customer open a temporary door for dembrane staff, and lets staff step through it for 24 hours. The door closes by itself. No one has to remember to revoke anything. There are two people in this story: the *customer* (a workspace admin or owner) who decides whether the door exists, and the *staff member* who walks through it. ## If you are a customer (workspace admin or owner) You control whether dembrane staff can ever get into your workspace. Access is off until you turn it on. ### Turning it on 1. Go to Workspace Settings, Access section. 2. Turn on *Allow dembrane staff to access this workspace for support*. That is the whole step. The toggle saves on its own, there is no Save button. While it is on, dembrane support staff can join your workspace as an admin to help you. Each time a staff member joins, their access ends automatically after 24 hours. ### What staff can and cannot do - A staff member who joins gets the *admin* role, the same level as your own admins, so they can see and act on the same things you can. - Their access is temporary. It expires 24 hours after they join. If they need longer they have to deliberately extend it, and it still expires again 24 hours later. - Only staff can join, and only while your toggle is on. The moment you turn the toggle off, no new staff can join. ### Turning it off Turn the same toggle off whenever you want. New staff joins are blocked immediately. Anyone already inside finishes their current 24-hour window, or leaves early. Turning the toggle off is your signal that you no longer want the door open. You usually will not need to turn it off yourself. When the last staff member leaves or their window expires, the toggle turns itself off, and we send you a notification and an email saying the session ended and access is now off. Turn it back on any time you need more help. ### Approving a request when the toggle is off If the toggle is off and a staff member needs to get in, they can send you a request instead of joining directly. You get a notification and an email, and a *Pending access requests* block appears in Workspace Settings, Access. Each request shows who is asking and an optional note about what they need. - *Approve* grants that one staff member admin access for 24 hours. It is a one-time grant: the toggle stays off, so approving one request does not open the door for everyone. - *Deny* declines the request. The staff member is told either way. A request that sits unanswered for 7 days expires on its own. ### Access history The Access section keeps a running history of what happened: toggles, requests, joins, extensions, and when access ended. Newest first, with *Show more* to page back. It is there so you can always see who had access and when, without asking anyone. ### The weekly reminder If support access stays on but no staff has joined for 7 days, we send a gentle reminder so a forgotten toggle does not stay open. Turn it off from the reminder, or leave it on if you still need help. ### Will this affect my bill? No. A staff member who joins for support does not count as a seat. Support access never changes what you are charged. ## If you are dembrane staff You join a customer workspace from the admin dashboard, one workspace at a time, and only when that customer has opted in. ### Joining 1. Open the admin dashboard and find the workspace in the list. 2. Open its actions, then the *Join for support* control. 3. Click *Join for support (24h)*. You now have admin access to that workspace for 24 hours. An *Open workspace* link appears so you can jump straight in. If the customer has not turned on support access, the join is refused with a clear message telling you so. You can either ask them to enable the toggle, or send a request (below). ### Requesting access when the toggle is off You do not have to wait for the customer to find the toggle. Open the *Join for support* control and choose *Request access*. Add a short note about what you need, or leave it blank. The workspace admins get a notification and an email, and approve or deny from their Workspace Settings. - If they approve, you get admin access for 24 hours, the same as a normal join. Their toggle stays off; the grant is just for you, just this once, so there is no *Extend* on an approved session. If you need longer, send another request. - If they deny, or the request goes unanswered for 7 days, you are told and the request closes. While a request is pending the control shows *Request sent*, with the option to cancel it. If you already belong to that workspace as a real member, joining does nothing harmful: it just tells you that you already have access, and it does not put a 24-hour expiry on your real membership. ### While you are in The control shows *You have support access to this workspace. It ends automatically on * so you always know when your window closes. - *Extend 24h*: resets the clock to 24 hours from now. Use this if a support session runs long. - *Leave now*: ends your access immediately, before the 24 hours are up. Good hygiene when you are done. ### When access ends You do not have to do anything. Access is revoked automatically at the expiry time. Even if something goes wrong with the scheduled revoke, a background sweep removes expired support access within about 15 minutes, so access never lingers. ## At a glance | | Customer | Staff | |---|---|---| | Where | Workspace Settings, Access | Admin dashboard, workspace actions | | Action | Toggle on or off, approve or deny requests | Join, Extend, Leave, Request access, Open workspace | | Role granted to staff | Admin | (receives admin) | | Duration | Until staff window expires | 24 hours per join, extendable | | Auto-revoke | Yes, after 24h | Yes, after 24h | | Toggle auto-off | Yes, when the last session ends | n/a | | Told about access events | Notifications, email, and access history | Told when a request is approved or denied | | Affects billing | No | No | --- # Trainings A *training* is a compliance course dembrane runs for people who use the platform in high-stakes settings - sensitive citizen consultations, vulnerable-group research, anything where mishandling people's words has real consequences. Completing one grants a *one-year licence* recorded against your account. Trainings are about people doing the work safely, not software features. You'd want one when a public body requires trained facilitators, when you're onboarding someone who'll collect from vulnerable participants, or when a client's procurement rules demand dated, demonstrable training for everyone touching the data. There's no self-serve "enrol" button. You request a training through your dembrane contact, and *staff* set it up - see [trainings & licences](../users/staff/trainings-and-licences.md). Hosts can *see* their own trainings and licences but don't create them. ## How it works 1. *You request a training* through your dembrane contact, usually because a client or setting requires it. 2. *Staff create it* in the admin panel, choosing the type (below) and the roster - the list of people taking it. 3. *People complete it.* On completion, each person gets a *training licence valid for one year*. 4. *The licence is recorded* against the user, and staff can review, edit, or revoke it if circumstances change. The licence is what proves someone was trained: it's dated, per-person, and expires after a year - so re-certification is a deliberate, visible step rather than something that quietly lapses. ## The three formats Trainings come in three formats, all granting the same one-year licence: - *Online* - delivered remotely. - *In person* - delivered face-to-face. - *Flex* - a mix of the two, for teams that can't all be in one place at once. The format is chosen when staff create the training. > [!TIP] > Request trainings early, before a sensitive engagement begins - the licence needs to be in > place when collection starts. If a client requires trained facilitators, raise it at the > planning stage. > [!NOTE] > A training licence is independent of your workspace [tier](./tiers-and-billing.md). It > certifies a *person* for high-risk work; it doesn't change your workspace's features. A > trained team on an appropriate tier is how you run sensitive work responsibly. ## Related - [Trainings & licences (staff)](../users/staff/trainings-and-licences.md) - how staff create trainings, manage rosters, and grant licences. - [Tiers & billing](./tiers-and-billing.md) - tiers cover features; trainings cover people. - [Data ownership & compliance](./data-ownership-and-compliance.md) - the wider compliance posture trainings support. --- # Licensing dembrane is open source under the *Business Source License 1.1 (BSL 1.1)*. The BSL is a source-available licence designed to keep the code open and learnable while protecting the project's ability to fund its own development. This page explains what that means in practice - what you can do for free, when you need a commercial licence, and who to talk to. > [!NOTE] > This page summarises the licence so you can make a decision. It is *not* legal advice and > it is *not* the licence text. The `LICENSE` file in the repository is the authoritative > source; read it before deploying, and take your own legal advice if your situation is at all > borderline. ## What you can do for free *Non-production use is unrestricted.* Read the code, run it locally, fork it, experiment, learn from it, build prototypes, contribute back - none of that is gated. This is the open part of "open source": the source is right there and you're welcome to use it. *Production use is free below a finance threshold.* You may run dembrane in production at no cost provided your organisation's *total finances are at or below €1,000,000 over any rolling twelve-month period*. For most individuals, small teams, non-profits, and early-stage projects, that means production use is free. If you cross that threshold and want to run dembrane in production, you need a [commercial licence](#commercial-licence). ## The Change Date - conversion to GPLv3 Each *release* of dembrane carries a *Change Date* of its *release date plus three years*. On that date, that release's licence automatically converts from BSL 1.1 to *GPLv3*. In other words: every version of dembrane becomes fully GPLv3 open source three years after it ships, regardless of the finance threshold. The BSL restriction is a rolling three-year window that always eventually opens. Newer releases reset the clock for *their* code; older releases keep converting on schedule. > [!TIP] > If you only need an older release and you're happy to wait, the GPLv3 conversion means the > restriction is time-limited by design. For current releases in production above the > threshold, the commercial licence is the path. ## Commercial licence If your organisation is above the €1M threshold and wants to run a current release in production, or you want terms the BSL doesn't grant (support, warranties, bespoke compliance, managed hosting), dembrane offers a *commercial licence*. Bespoke compliance arrangements and self-hosting support are available alongside it. The managed service at dembrane.com is the turnkey alternative - see [tiers & billing](../../features/tiers-and-billing.md). Changemaker and above is where most teams land; the EU-sovereign Guardian tier is *coming soon*. ## At a glance | Your situation | Under BSL 1.1 | |---|---| | Local dev, prototyping, learning, forking | Free, unrestricted (non-production). | | Production, organisation finances ≤ €1M / 12 months | Free. | | Production, organisation finances > €1M / 12 months | Needs a [commercial licence](#commercial-licence). | | Using a release ≥ 3 years after its release date | GPLv3 (the Change Date has passed). | ## Who to contact | Topic | Contact | |---|---| | Pull requests, security | sameer@dembrane.com | | Legal, licensing, stewardship | bram@dembrane.com | | Mission, press | jorim@dembrane.com | | Hosting, commercial arrangements | evelien@dembrane.com | For commercial-licence and self-hosting-support enquiries, *evelien@dembrane.com* (hosting / commercial) or *bram@dembrane.com* (legal / stewardship) are the right starting points. ## Related - [Contributing](./contributing.md) - the CLA and how to send changes. - [Building on dembrane (overview)](./index.md) - what's open source. - [Self-hosting](./self-hosting.md) - running it yourself. - [Tiers & billing](../../features/tiers-and-billing.md) - the managed alternative. --- # Self-hosting dembrane Running dembrane yourself means standing up a small set of services and pointing them at your own database, object storage, and language-model providers. This page is the orientation: the moving parts, how to bring them up locally, the ports they listen on, and where the configuration lives. > [!NOTE] > Read the [licensing](./licensing.md) terms before you run dembrane in production. The code > is BSL 1.1: non-production use is unrestricted; production use is free below the €1M finance > threshold and otherwise needs a commercial licence. ## When you'd self-host - You need your data and audio to stay on infrastructure you control, in a region you choose. - You want to bring your own language-model providers (your own keys, your own regions) rather than use the managed defaults. - You're contributing to the project and need it running locally - see [contributing](./contributing.md). If none of those apply, the [managed service](../../features/tiers-and-billing.md) at dembrane.com saves you the operational work. ## The services you'll run dembrane is a handful of cooperating services. You run all of them. | Service | Port | What it does | |---|---|---| | *FastAPI backend* | `8000` | The API: v1 routes under `/api/*`, v2 under `/api/v2/*`, plus the BFF layer `api/v2/bff/*`. | | *Agent service* | `8001` | Agentic chat (tool-using "Ask"); leases coordinated in Redis. | | *Directus* | `8055` | The data layer, authentication, and file storage. | | *Workers* (`network`, `cpu`) | - | Background jobs via Dramatiq: transcription, merge, summaries, reports. | | *Scheduler* | - | APScheduler dispatching periodic jobs (billing, digests, reconciliation) to the workers. | | *Dashboard* (web) | `5173` | The host dashboard frontend. | | *Participant portal* (web) | `5174` | The no-account recording experience. | The dashboard and the portal are the *same frontend codebase*; it picks the right router by hostname, which is why they're two ports in development. For a code-level tour of how these fit together, see the internal [architecture](../developer-internal/architecture.md) and [background jobs & scheduler](../developer-internal/background-jobs-and-scheduler.md) guides. ## Backing infrastructure These are the dependencies the services need. You can run them in the dev container, on your own boxes, or as managed cloud services. - *PostgreSQL with the `pgvector` extension* - the primary database. pgvector is required; embeddings for chat and analysis are stored as vectors. - *Redis or Valkey* - the message broker for the workers, distributed locks for idempotency, the agent service's leases, and the pub/sub channel that drives live (SSE) progress updates. Valkey is a drop-in Redis replacement and is what the managed deployment uses. - *S3-compatible object storage* - for audio chunks and generated files. Bring your own bucket (AWS S3, DigitalOcean Spaces, OVHcloud, …) or run *MinIO* locally. - *Language-model providers* - at minimum a set of keys for the model groups dembrane uses. See [configuration & LLM providers](./configuration-and-llm-providers.md). - *A transcription provider* - Gemini (Vertex AI), or a transcription model routed through LiteLLM. ## Running it locally: the dev container + mprocs The repository ships a *dev container* (under `.devcontainer/`) that provisions the tooling and local infrastructure for you: `pnpm` and `uv` for the JavaScript and Python toolchains, plus local *PostgreSQL*, *Valkey*, and *Directus*. Opening the repo in a dev-container-aware editor builds it once and drops you into a ready environment. Inside the container, the services are orchestrated with `mprocs`, driven by `mprocs.yaml`. A single `mprocs` invocation brings up: - `server` - the FastAPI backend (`8000`); - `workers` - the `network` queue (gevent, for async I/O like transcription and summaries); - `workers-cpu` - the `cpu` queue; - `scheduler` - the periodic-job dispatcher; - `admin-dashboard` - the host dashboard on `5173`; - `participant-portal` - the portal on `5174`. `mprocs` gives you one pane per process, so you can read each service's logs and restart any one of them independently. The internal [local development](../developer-internal/local-development.md) guide covers the day-to-day workflow in more detail. > [!TIP] > Bring your own S3, or run MinIO locally. If you point `STORAGE_S3_*` at a MinIO instance > in the same network, the participant upload flow (presigned URLs → confirm) works exactly as > it does in production. See [the participant API](./participant-api.md) for that sequence. ## Configuration: environment files Configuration is by environment variable, split across the services: - `server/.env` - the backend, workers, and scheduler. Copy from `server/.env.sample` and fill in: the database URL, the Redis/Valkey URL, the S3 credentials and endpoint, the language-model keys (the `LLM__*` scheme - see [configuration & LLM providers](./configuration-and-llm-providers.md)), the transcription provider keys, and the Directus connection. - `directus/.env` - Directus's own configuration: its database, secret/keys, admin credentials, and storage driver. Keep secrets out of version control. The `.env.sample` files are the canonical list of what each service expects; treat them as the source of truth when a variable here and the code disagree. > [!IMPORTANT] > Directus owns authentication and file storage. The backend talks to Directus for both, so > the two services must agree on their shared secrets and connection details. How the backend > trusts Directus-issued tokens is covered in [authentication](./authentication.md). ## A first-run checklist 1. Provision PostgreSQL *with pgvector*, Redis/Valkey, and an S3 bucket (or MinIO). 2. Copy `server/.env.sample` → `server/.env` and `directus/.env` and fill them in. 3. Configure at least one deployment per language-model group and a transcription provider - see [configuration & LLM providers](./configuration-and-llm-providers.md). 4. Bring up Directus (`8055`) and apply its schema/migrations. 5. Start the backend (`8000`), the workers, and the scheduler. 6. Start the dashboard (`5173`) and the portal (`5174`). 7. Set `SERVE_API_DOCS=1` while you're integrating, so the OpenAPI explorer is available at `/docs` and `/redoc`. See [the participant API](./participant-api.md). ## EU residency dembrane is built and operated with European data residency in mind, and the self-hosted stack can be configured the same way. The levers: - *Language models in EU regions.* Route every model group through EU-hosted deployments - for example Google Vertex AI in `europe-west1` / `europe-west4`, or Azure OpenAI in West Europe / Sweden Central. The per-group, per-region scheme is in [configuration & LLM providers](./configuration-and-llm-providers.md). - *EU object storage.* Point the S3 configuration at an EU bucket/endpoint (for example an OVHcloud or EU-region Spaces bucket). - *EU transactional email.* If you wire up outbound email, use an EU sub-user/region (for example a SendGrid EU sub-user). - *EU database and Redis.* Run PostgreSQL and Valkey in your chosen region. > [!NOTE] > On the managed service, the fully *EU-sovereign* stack (CLOUD-Act-safe hosting and > sovereign models) is the *Guardian* tier and is *coming soon*. When you self-host you > assemble residency from your own choice of regions and providers; the configuration scheme > is designed to make that straightforward. See > [tiers & billing](../../features/tiers-and-billing.md) and > [data ownership & compliance](../../features/data-ownership-and-compliance.md). ## Related - [Configuration & LLM providers](./configuration-and-llm-providers.md) - [Authentication](./authentication.md) - [The participant API](./participant-api.md) - [Internal: architecture](../developer-internal/architecture.md) - [Internal: local development](../developer-internal/local-development.md) - [Licensing](./licensing.md) --- # Configuration & LLM providers When you [self-host dembrane](./self-hosting.md) you bring your own language models. dembrane doesn't hard-code a provider: it routes every model call through a *LiteLLM router* that you configure entirely with environment variables. This page covers that scheme, the transcription and embedding configuration, choosing EU regions, and the feature toggles you'll most often reach for. > [!NOTE] > The canonical, code-derived reference for these variables is `echo/docs/litellm_config.md` > in the repository. This page explains the shape and the decisions; keep that file open > alongside it for the exhaustive list and the startup-log examples. ## Model groups Rather than naming a model per feature, dembrane groups model calls by capability. You configure each *group*, and the code asks the router for the right group at the right time. | Group | Used for | Audio | |---|---|---| | `MULTI_MODAL_PRO` | Chat, reports, replies, artifact generation (Gemini 2.5 Pro by default) | Yes | | `MULTI_MODAL_FAST` | Realtime verification (Gemini 2.5 Flash) | Yes | | `TEXT_FAST` | Summaries, chat streaming, auto-select (text only) | No | `MULTI_MODAL_*` groups must be backed by models that accept *audio* input (Gemini does), as they're used in the [processing pipeline](../developer-internal/processing-pipeline.md). `TEXT_FAST` is text-only. ## The `LLM__[_n]__*` scheme Each group has a *primary* deployment and any number of *fallback* deployments. The variable name encodes the group, the (optional) deployment index, and the parameter: ``` LLM____ # primary deployment LLM_____ # fallback deployment n (1, 2, 3, …) ``` A minimal single-deployment group: ```bash LLM__TEXT_FAST__MODEL=azure/gpt-4o-mini LLM__TEXT_FAST__API_BASE=https://westeurope.openai.azure.com LLM__TEXT_FAST__API_KEY=sk-azure-west-... LLM__TEXT_FAST__API_VERSION=2024-02-15-preview ``` The exact set of `` keys depends on the provider - `MODEL`, `API_KEY`, `API_BASE`, `API_VERSION` for OpenAI/Azure; `VERTEX_LOCATION`, `VERTEX_PROJECT`, `VERTEX_CREDENTIALS` for Google Vertex AI, and so on. They map onto the parameters LiteLLM expects for that provider. ### Weighting and failover Add numbered deployments to the same group and the router load-balances and fails over across them automatically: ```bash # Primary LLM__TEXT_FAST__MODEL=azure/gpt-4o-mini LLM__TEXT_FAST__API_BASE=https://westeurope.openai.azure.com LLM__TEXT_FAST__API_KEY=sk-azure-west-... LLM__TEXT_FAST__API_VERSION=2024-02-15-preview # Fallback 1 LLM__TEXT_FAST_1__MODEL=azure/gpt-4o-mini LLM__TEXT_FAST_1__API_BASE=https://swedencentral.openai.azure.com LLM__TEXT_FAST_1__API_KEY=sk-azure-sweden-... LLM__TEXT_FAST_1__API_VERSION=2024-02-15-preview # Fallback 2 LLM__TEXT_FAST_2__MODEL=vertex_ai/gemini-2.0-flash LLM__TEXT_FAST_2__VERTEX_LOCATION=europe-west1 LLM__TEXT_FAST_2__VERTEX_PROJECT=dembrane-prod LLM__TEXT_FAST_2__VERTEX_CREDENTIALS=${GCP_SA_JSON} ``` - *Weight is inferred from the suffix.* The primary gets weight `10`, `_1` gets `9`, `_2` gets `8`, and so on. Higher-weighted deployments receive proportionally more traffic. - *Retries:* three attempts with exponential backoff. - *Cooldowns:* a deployment that fails three times is cooled down for 60 seconds, during which traffic shifts to the healthy deployments. - *Distributed state:* the router shares its health/cooldown state via the same Redis/Valkey you configured for the workers, so all backend and worker processes agree. At startup the backend logs a deployment summary - how many deployments each group has, their models, regions, roles (primary/fallback), and weights. Read those lines first when a group isn't behaving as expected; they tell you exactly what the router parsed from your environment. ## Transcription Transcription is the first step of the [pipeline](../developer-internal/processing-pipeline.md). You choose the provider via the `TRANSCRIPTION_PROVIDER` environment variable: - *Gemini Vertex AI (Dembrane-26-07)* - chunk audio is transcribed directly on Gemini 2.5 Pro deployed in Vertex AI (`europe-west1`). This is a single-pass workflow that performs transcription, hotword normalization, and optional PII redaction. Configure `GCP_SA_JSON` with your Google Cloud service account key. - *LiteLLM* - route a speech-to-text model through LiteLLM instead. See [transcription](../../features/transcription.md) for the host-facing view. ## Embeddings Chat and library analysis search over *embeddings* stored in pgvector. Configure an embedding model (for example an Azure or Vertex embedding deployment) in `server/.env` - the `LIGHTRAG_LITELLM_EMBEDDING_*` variables documented in `echo/docs/litellm_config.md`. Without a working embedding model, retrieval-augmented [chat & Ask](../../features/chat-and-ask.md) has nothing to retrieve over. ## EU regions Because every deployment names its own region, residency is a configuration choice. A worked EU-only example, mixing Azure and Vertex across European regions: ```bash # TEXT_FAST: Azure West Europe (primary) + Sweden Central + Gemini EU LLM__TEXT_FAST__MODEL=azure/gpt-4o-mini LLM__TEXT_FAST__API_BASE=https://westeurope.openai.azure.com LLM__TEXT_FAST__API_KEY=sk-azure-west-... LLM__TEXT_FAST__API_VERSION=2024-02-15-preview LLM__TEXT_FAST_1__MODEL=azure/gpt-4o-mini LLM__TEXT_FAST_1__API_BASE=https://swedencentral.openai.azure.com LLM__TEXT_FAST_1__API_KEY=sk-azure-sweden-... LLM__TEXT_FAST_1__API_VERSION=2024-02-15-preview # MULTI_MODAL_PRO: Gemini in EU regions (audio required) LLM__MULTI_MODAL_PRO__MODEL=vertex_ai/gemini-2.5-pro LLM__MULTI_MODAL_PRO__VERTEX_LOCATION=europe-west1 LLM__MULTI_MODAL_PRO__VERTEX_PROJECT=dembrane-prod LLM__MULTI_MODAL_PRO__VERTEX_CREDENTIALS=${GCP_SA_JSON} LLM__MULTI_MODAL_PRO_1__MODEL=vertex_ai/gemini-2.5-pro LLM__MULTI_MODAL_PRO_1__VERTEX_LOCATION=europe-west4 LLM__MULTI_MODAL_PRO_1__VERTEX_PROJECT=dembrane-prod LLM__MULTI_MODAL_PRO_1__VERTEX_CREDENTIALS=${GCP_SA_JSON} ``` Pair EU model regions with EU [object storage and email](./self-hosting.md#eu-residency) for an end-to-end European footprint. ## Key feature toggles A few environment toggles change behaviour you'll care about while integrating or operating: - `SERVE_API_DOCS` - set to `1` to expose the OpenAPI explorer at `/docs` and the ReDoc view at `/redoc`. Invaluable while building against [the participant API](./participant-api.md) or [export endpoints](./export-and-integrations.md). Leave it off in production if you don't want the schema public. - `DISABLE_REDACTION` - disables the PII-redaction step in the transcript correction pass. Only do this if you have a deliberate reason; redaction is on by design. - `ENABLE_CHAT_AUTO_SELECT` - turns on the auto-select feature that picks relevant conversations for a chat (off by default). - `ENABLE_AUDIO_LIGHTRAG_INPUT` - enables the audio-LightRAG input path (off by default). The audio-LightRAG knobs (`AUDIO_LIGHTRAG_*`), the LightRAG model variables (`LIGHTRAG_LITELLM_*`), and the full toggle list are enumerated in `echo/docs/litellm_config.md`. When a toggle here and the code disagree, trust the code and that file. > [!WARNING] > `DISABLE_REDACTION` removes a privacy safeguard from transcripts. If you handle personal > data, leave redaction on and review your obligations - see > [data ownership & compliance](../../features/data-ownership-and-compliance.md). ## Related - [Self-hosting](./self-hosting.md) - [The participant API](./participant-api.md) - [Transcription](../../features/transcription.md) - [Chat & Ask](../../features/chat-and-ask.md) - [Internal: the processing pipeline](../developer-internal/processing-pipeline.md) --- # Authentication dembrane's data, authentication, and file storage all live in *Directus*. The FastAPI backend doesn't run its own user database; it trusts tokens issued by Directus and reads the claims inside them. So "authenticating against dembrane" almost always means "presenting a valid Directus token". This page explains the three ways to do that and how the backend interprets what it receives. > [!NOTE] > This page is about the *authenticated* API (the dashboard and integrations). The > [participant API](./participant-api.md) is deliberately unauthenticated - that's how someone > can record via a link with no account. ## How the backend reads a request The backend's auth dependency (`dependency_auth.py`) looks for a Directus session token in one of two places, in this order: 1. A cookie named `directus_session_token` (this is how the browser-based dashboard and portal authenticate - Directus sets the cookie on login). 2. An `Authorization: Bearer ` header (this is how server-to-server integrations authenticate). Either way, the token is validated as a Directus JWT and its claims are used to identify the user and their permissions. There's no separate dembrane login: a valid Directus token is a valid dembrane request. ## Obtaining a token via Directus For an integration, log in against your Directus instance and use the access token it returns: ```bash curl -X POST https://YOUR-DIRECTUS-HOST:8055/auth/login \ -H 'Content-Type: application/json' \ -d '{"email":"you@example.org","password":"••••••••"}' ``` Directus replies with an `access_token` (a short-lived JWT) and a `refresh_token`. Send the access token as a bearer token on subsequent calls to the dembrane backend: ```bash curl https://YOUR-API-HOST:8000/api/v2/... \ -H "Authorization: Bearer $ACCESS_TOKEN" ``` When the access token expires, exchange the refresh token at Directus's `/auth/refresh` endpoint for a fresh pair. (Directus is the authority here; its [authentication documentation](https://directus.io/docs) covers refresh, logout, and 2FA in full. dembrane's dashboard supports two-factor authentication on login.) > [!TIP] > For local development with [self-hosting](./self-hosting.md), your Directus admin > credentials come from `directus/.env`. Logging in with them gives you a token whose claims > include `admin_access` (see below). ## Static tokens for integrations For a long-lived, non-interactive integration - a backend job, a sync script - a per-session login is awkward. Directus supports *static access tokens*: assign one to a dedicated service user in Directus, and send it as the bearer token. dembrane reads it from the environment as `DIRECTUS_TOKEN` for its own server-to-server calls, and you can mint equivalent tokens for your integrations. > [!IMPORTANT] > A static token carries the full permissions of the user it's attached to and doesn't > expire on its own. Treat it like a password: scope its user to exactly what the integration > needs, store it as a secret, and rotate it if it leaks. Prefer a narrowly-permissioned > service user over reusing an admin token. ## The `admin_access` claim (staff) dembrane has a notion of *staff* - dembrane employees who operate the [admin panel](../developer-internal/roles-and-policies.md). Staff status is *not* a dembrane role in the [roles & permissions](../../features/roles-and-permissions.md) sense; it's a JWT claim, `admin_access`, that Directus sets when the user has the Directus admin role. The backend gates the staff-only endpoints (everything under `/api/v2/admin/*`, plus actions like setting a tier or transferring a workspace) on `admin_access == true`. If you self-host, your own Directus admins will carry this claim - which means they can reach the admin/billing surface. Grant the Directus admin role deliberately. The everyday [org and workspace roles](../../features/roles-and-permissions.md) (owner, admin, member, billing, external, observer) are evaluated separately, per organisation and per workspace, against the policies in `policies.py`. `admin_access` sits above all of that and is for dembrane-operations use. ## Which token for which job | You're building… | Use | |---|---| | A browser app on top of the dashboard | The `directus_session_token` cookie (set by Directus login). | | A server-to-server integration | A bearer token - a static `DIRECTUS_TOKEN`-style token on a scoped service user. | | A short-lived script | `POST /auth/login` → use the `access_token` as a bearer token; refresh as needed. | | Recording from a public link | Nothing - use the unauthenticated [participant API](./participant-api.md). | ## Related - [The participant API](./participant-api.md) - the unauthenticated endpoints. - [Webhooks](./webhooks.md) - outbound events (signed, not bearer-authenticated). - [Export & integrations](./export-and-integrations.md) - authenticated export endpoints. - [Roles & permissions](../../features/roles-and-permissions.md) - the org/workspace role model. - [Self-hosting](./self-hosting.md) - where Directus fits in the stack. --- # The participant API The participant API is the set of *unauthenticated* endpoints that power the [participant portal](../../features/portal-and-participant-experience.md). It's how someone can scan a QR code or open a link, record a conversation, and have it land in your project - without ever creating an account. If you're building your own recorder or kiosk on top of dembrane, this is the surface you'll use. These routes live in `server/dembrane/api/participant.py` and are served under `/api/participant/*` by the [FastAPI backend](./self-hosting.md) on port `8000`. > [!NOTE] > "Unauthenticated" means no user token is required - the project's identifier is the > capability. Anyone with a project's public link can initiate and upload conversations to it, > which is the point. Don't treat a project ID as a secret. Everything authenticated lives > behind [Directus tokens](./authentication.md) instead. ## OpenAPI / interactive docs Set `SERVE_API_DOCS=1` (see [configuration](./configuration-and-llm-providers.md#key-feature-toggles)) and the backend serves: - `/docs` - the interactive Swagger UI explorer; - `/redoc` - the ReDoc reference. These render the live schema for your build, including request/response shapes for every endpoint below. Keep them on while integrating; they're the authoritative parameter list. ## Reading public project data Fetch the public metadata a recorder needs to render the start screen: | Method & path | Returns | |---|---| | `GET /api/participant/projects/{pid}` | Public project metadata - title, language, the portal-editor configuration (welcome text, whether to ask for name/email, verification settings). | | `GET /api/participant/projects/{pid}/conversations/{cid}` | A single conversation's public state. | | `GET /api/participant/conversations/{cid}/chunks` | The chunks recorded so far for a conversation. | The portal-editor fields returned here are what the [host configured](../../features/portal-editor.md) for the participant experience. ## Initiating a conversation Create a conversation to record into: ```http POST /api/participant/conversations/initiate Content-Type: application/json { "project_id": "", "name": "Optional participant name", "email": "optional@example.org", "tag_id_list": ["", "..."], "source": "PORTAL_AUDIO" } ``` Whether `name` and `email` are expected depends on the project's portal-editor settings (ask for name / ask for email). The response carries the new conversation's ID, which you use for every upload call that follows. ## The upload sequence dembrane records in *chunks* (the portal uses ~30-second chunks). Each chunk goes to S3-compatible storage via a presigned URL, then is confirmed so the backend can enqueue transcription. The typical loop: 1. *Get a presigned upload URL.* ```http POST /api/participant/conversations/{cid}/get-upload-url ``` Returns a presigned S3 URL (and the object key) to `PUT` the chunk to directly. > [!IMPORTANT] > This endpoint is *rate-limited to 40 requests per minute*. One presigned URL per chunk, > so a long recording made of short chunks will approach that ceiling - pace your requests. 2. *Upload the bytes* to the presigned URL (a direct `PUT` to S3/MinIO - this doesn't go through the dembrane backend, which is what keeps large uploads off the API). 3. *Confirm the upload* so the backend knows the chunk has landed and can process it: ```http POST /api/participant/conversations/{cid}/confirm-upload ``` Repeat 1–3 for each chunk as the recording proceeds. ### Alternatives to the presigned flow - `POST /api/participant/conversations/{cid}/upload-chunk` - a *multipart* upload that sends the audio through the backend directly, for cases where a direct-to-S3 `PUT` isn't practical. - `POST /api/participant/conversations/{cid}/upload-text` - submit *typed* text instead of audio (the portal's "type instead of speak" path). - `POST /api/participant/conversations/{cid}/check-s3` - a connectivity check the portal runs to confirm the client can reach object storage before it starts recording. Use it to fail fast rather than discovering a broken upload mid-session. ## What happens after upload Once chunks are confirmed, the [processing pipeline](../developer-internal/processing-pipeline.md) takes over: each chunk is transcribed, corrected (key terms + redaction), and - when the conversation is finished and all chunks are processed - merged and summarised. You can poll the chunk and conversation endpoints to follow progress, and the host dashboard shows the same state live. See [transcription](../../features/transcription.md) for what each stage does. ## Participant report endpoints If the project enables a participant-facing report, the participant API also exposes endpoints to fetch that report and its artifacts, and to unsubscribe from notifications. These back the portal's *finish* and *report* screens; their exact shapes are in the `/docs` explorer for your build. See [your report](../../features/portal-and-participant-experience.md) for the participant-side view. ## A minimal end-to-end flow ```text GET /api/participant/projects/{pid} → render start screen POST /api/participant/conversations/initiate → conversation {cid} loop while recording: POST /api/participant/conversations/{cid}/check-s3 → ok to upload? POST /api/participant/conversations/{cid}/get-upload-url → presigned URL (≤ 40/min) PUT (the chunk bytes) → straight to S3/MinIO POST /api/participant/conversations/{cid}/confirm-upload → enqueue processing finish: (mark finished; fetch participant report if enabled) ``` ## Related - [The participant portal](../../features/portal-and-participant-experience.md) - what this API drives. - [The portal editor](../../features/portal-editor.md) - the settings returned by the project endpoint. - [Configuration & LLM providers](./configuration-and-llm-providers.md) - `SERVE_API_DOCS` and providers. - [Authentication](./authentication.md) - for the *authenticated* surface. - [Internal: the processing pipeline](../developer-internal/processing-pipeline.md) - what happens to a chunk. --- # Webhooks Webhooks let dembrane call *your* systems when something happens in a project - a conversation finishes transcribing, a report is generated. Instead of polling the API, you register an endpoint and dembrane `POST`s a payload to it as events occur. Use them to push transcripts into a data warehouse, notify a Slack channel, kick off your own analysis, or sync state into a CRM. For the host-facing, point-and-click view of the same feature, see [webhooks & integrations](../../features/webhooks-and-integrations.md). This page is the developer reference. > [!IMPORTANT] > Webhooks are gated to *Changemaker and above*. On the managed service you'll need a > Changemaker (or Guardian) workspace to use them; see > [tiers & billing](../../features/tiers-and-billing.md). When you > [self-host](./self-hosting.md), you operate the whole platform. ## Events A webhook is registered against a project and fires for these events: | Event | When it fires | |---|---| | `conversation.started` | A participant begins a conversation in the project. | | `conversation.transcribed` | A conversation's audio has been transcribed. | | `conversation.summarized` | A conversation's summary has been generated. | | `report.generated` | A report has finished generating. | These line up with the stages of the [processing pipeline](../developer-internal/processing-pipeline.md): `started` at capture, `transcribed` then `summarized` as a conversation is processed, and `report.generated` when a report completes. ## Managing webhooks (API) Webhook endpoints are managed under a project's `webhooks` collection. All of these require an [authenticated request](./authentication.md) (a Directus token) with the right [workspace permissions](../../features/roles-and-permissions.md) - `workspace:webhooks` is an admin/owner capability. | Method & path | Action | |---|---| | `GET /api/projects/{pid}/webhooks` | List the project's webhooks. | | `POST /api/projects/{pid}/webhooks` | Create a webhook (target URL, events, optional secret). | | `PATCH /api/projects/{pid}/webhooks/{id}` | Update a webhook (URL, events, secret, enabled). | | `DELETE /api/projects/{pid}/webhooks/{id}` | Remove a webhook. | | `POST /api/projects/{pid}/webhooks/{id}/test` | Send a test delivery to the registered URL. | | `GET /api/projects/{pid}/webhooks/{id}/copyable` | Get a copyable representation (for sharing/setup). | > [!TIP] > After creating a webhook, hit the `/test` endpoint. It sends a delivery to your URL so you > can confirm your receiver is reachable and your signature verification works before any real > event arrives. ## The payload Deliveries are `POST`ed to your URL as JSON. Each payload identifies the event type and carries the relevant identifiers and data for that event (for example, the conversation ID for a `conversation.*` event, or the report ID for `report.generated`). The exact field set is visible in the `/copyable` output and in the `/test` delivery - inspect those for the shape your build produces rather than hard-coding fields. The implementation lives in `service/webhook.py` if you're reading along in the code. ## Verifying deliveries: `X-Dembrane-Signature` If you set a *secret* on the webhook, every delivery includes an `X-Dembrane-Signature` header containing an *HMAC-SHA256* of the request body, keyed by your secret. Verify it before trusting a payload - this is how you confirm a delivery really came from dembrane and wasn't replayed or forged. ```python import hashlib import hmac def is_valid(body: bytes, signature_header: str, secret: str) -> bool: expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest() # constant-time compare against the value in X-Dembrane-Signature return hmac.compare_digest(expected, signature_header) ``` > [!WARNING] > Always compute the HMAC over the *raw request body bytes*, exactly as received - not over a > re-serialised object. Re-encoding JSON can reorder keys or change whitespace and break the > comparison. Use a constant-time compare (`hmac.compare_digest`), and reject any delivery > whose signature doesn't match. If you don't set a secret, deliveries are sent unsigned - fine for a closed network, but set a secret for anything reachable from the public internet. ## Good practices - *Respond fast, process later.* Acknowledge the delivery with a `2xx` quickly and do the real work asynchronously. A slow or failing receiver shouldn't hold up dembrane. - *Be idempotent.* Treat events as at-least-once; a delivery may arrive more than once. - *Verify first.* Check the signature before doing anything with the payload. ## Related - [Webhooks & integrations](../../features/webhooks-and-integrations.md) - the host-facing feature page. - [Authentication](./authentication.md) - tokens for the management endpoints. - [Export & integrations](./export-and-integrations.md) - for pulling data rather than receiving pushes. - [Tiers & billing](../../features/tiers-and-billing.md) - the Changemaker gate. - [Internal: the processing pipeline](../developer-internal/processing-pipeline.md) - what triggers each event. --- # Export & integrations Your data is yours. dembrane gives you several ways to get conversations, transcripts, and analysis back out - for archiving, for feeding another tool, or for building your own integration. This page covers the programmatic export endpoints and the patterns around them. For the host-facing, button-driven version of the same capability, see [export & data portability](../../features/export-and-data-portability.md). This page is the developer reference; if you'd rather be *pushed* events than pull them, see [webhooks](./webhooks.md). > [!NOTE] > Export endpoints are part of the *authenticated* API. Send a > [Directus token](./authentication.md) with the [workspace permission](../../features/roles-and-permissions.md) > to export (`workspace:export`, an admin/owner capability). Exporting from the participant > side is the [participant report](./participant-api.md) flow instead. ## Transcript zip (whole project) Export every conversation in a project as a zip of per-conversation Markdown files: ```http GET /api/projects/{pid}/transcripts Authorization: Bearer ``` Returns a zip archive - one Markdown file per conversation, each containing that conversation's transcript. This is the simplest way to take a full point-in-time copy of a project's spoken record. ```bash curl -L https://YOUR-API-HOST:8000/api/projects/$PID/transcripts \ -H "Authorization: Bearer $TOKEN" \ -o project-transcripts.zip ``` ## Per-conversation transcript (plain text) For a single conversation, fetch the transcript as plain text: ```http GET /api/conversations/{cid}/transcript Authorization: Bearer ``` Useful when you want to stream one conversation into another system as it finishes - pair it with a `conversation.summarized` [webhook](./webhooks.md) to grab each transcript at the moment it's ready, rather than polling. ## CSV / Excel The host dashboard's [integrations](../../features/export-and-data-portability.md) screen produces *CSV* and *Excel* exports of conversations and their metadata, alongside the transcript zip. These are the tabular companions to the Markdown export - the right shape when you're loading into a spreadsheet, a BI tool, or a data warehouse. > [!TIP] > Use the Markdown/transcript exports when you care about the *content* (the words), and the > CSV/Excel exports when you care about the *structure* (which conversations exist, their > tags, timestamps, and status). Many integrations pull both: the CSV for the index, the zip > for the bodies. ## Reports Reports are generated artifacts assembled from a project's conversations (a two-phase fan-out-then-generate job - see the [processing pipeline](../developer-internal/processing-pipeline.md)). A finished report can be exported to PDF from the dashboard, and the `report.generated` [webhook](./webhooks.md) tells your systems the moment one is ready to fetch. See [reports](../../features/reports.md) for the host-facing view. ## Programmatic export patterns A few patterns that hold up well: - *Scheduled full snapshot.* On a cron, call `GET /api/projects/{pid}/transcripts` and store the zip in your own archive. Simple, complete, and easy to diff between runs. - *Event-driven incremental pull.* Register a [webhook](./webhooks.md) for `conversation.summarized` (and `conversation.transcribed`), and on each delivery fetch that one conversation's transcript via `GET /api/conversations/{cid}/transcript`. Low latency, no polling, and you only fetch what changed. - *Index + bodies.* Pull the CSV/Excel export for the conversation index and metadata, then fetch transcript bodies only for the rows you care about. > [!IMPORTANT] > Exports can contain personal data. The transcript correction pass redacts PII by default > (unless `DISABLE_REDACTION` is set - see > [configuration](./configuration-and-llm-providers.md#key-feature-toggles)), but you remain > responsible for how you store and process exported data. Review > [data ownership & compliance](../../features/data-ownership-and-compliance.md). ## Related - [Export & data portability](../../features/export-and-data-portability.md) - the host-facing feature. - [Webhooks](./webhooks.md) - be notified when there's something new to export. - [Authentication](./authentication.md) - tokens for these endpoints. - [Reports](../../features/reports.md) - what a generated report contains. - [Data ownership & compliance](../../features/data-ownership-and-compliance.md). --- # MCP & bring-your-own-LLM Bring-your-own-LLM lets you connect an assistant you already use - ChatGPT, Claude - to your dembrane data, so it can reason over your conversations directly instead of dembrane choosing the model for you. This page is the developer reference. For the product-level overview of the same feature, see [MCP & bring-your-own-LLM](../../features/mcp-and-bring-your-own-llm.md). > [!IMPORTANT] > This is a *coming-soon* feature, tied to the *Innovator* tier. The pieces below describe > the intended offering; it has not shipped yet. We mark it clearly so you can plan, not so you > can build against it today. ## What it will be [MCP](https://modelcontextprotocol.io) - the Model Context Protocol - is an open standard for giving an assistant access to external tools and data through a well-defined server interface. The dembrane offering will expose your dembrane workspace as an *MCP server* that your own assistant can connect to. The intent, as set out in the tier model (ADR 0005): - On *Innovator*, the chat screen becomes a *bring-your-own-LLM integration* rather than using dembrane's built-in analysis model. - You'll connect an assistant you already pay for - *ChatGPT*, *Claude*, or another MCP-capable client - to your dembrane data via the MCP server. - Your assistant can then query your conversations and transcripts as tools, with dembrane acting as the grounded, permission-aware data source. Your words stay in dembrane; the model reasons over them through the protocol. This is distinct from *built-in analysis* (the EU-hosted Gemini-powered [chat & Ask](../../features/chat-and-ask.md) and [library & analysis](../../features/library-and-analysis.md)), which arrives at *Changemaker*. Innovator gives you the connector; Changemaker gives you dembrane's own analysis. See [tiers & billing](../../features/tiers-and-billing.md) for how the tiers stack. ## Current status To be unambiguous about what exists today: - The MCP / bring-your-own-LLM connector for end users is *not shipped*. Innovator is gated on it shipping. - The agentic [chat & Ask](../../features/chat-and-ask.md) that *does* exist is dembrane's own agent service ([the internal chat & agent guide](../developer-internal/chat-and-agent.md)) using its configured models - it is not an exposed MCP server you connect ChatGPT or Claude to. > [!NOTE] > If you've cloned the repository and found an `.mcp.json` file, that's *internal > developer tooling* - MCP configuration for engineers working on the codebase. It is *not* > an exposed dembrane MCP server, and it is unrelated to the customer-facing bring-your-own-LLM > offering described here. Don't treat it as a public integration point. ## What you can do today While the connector is in development, the supported ways to build your own analysis on top of dembrane data are the existing developer surfaces: - *Pull the data* with the [export endpoints](./export-and-integrations.md) - transcript zips and per-conversation text - and feed it into your own assistant or pipeline. - *React to events* with [webhooks](./webhooks.md) so your own tooling sees new transcripts and reports as they're produced. - *Self-host and configure your own models.* When you [self-host](./self-hosting.md), you already bring your own LLM keys and regions via the [LiteLLM configuration](./configuration-and-llm-providers.md) - that's bring-your-own-*provider* for dembrane's built-in features, which is a different thing from the MCP connector but worth knowing if your goal is "my models, my data location". ## Related - [MCP & bring-your-own-LLM (feature)](../../features/mcp-and-bring-your-own-llm.md) - [Chat & Ask](../../features/chat-and-ask.md) - the analysis that exists today. - [Tiers & billing](../../features/tiers-and-billing.md) - Innovator vs Changemaker. - [Export & integrations](./export-and-integrations.md) - building on dembrane data now. - [Configuration & LLM providers](./configuration-and-llm-providers.md) - your models, your regions. --- # Contributing dembrane is built in the open, and contributions are welcome. Whether you've found a bug, written a fix, or want to add a feature, this page explains how to get your change in - and how we keep the project safe and maintainable while doing it. The guiding principle is the same one behind the product: *PEOPLE KNOW HOW*. The people using dembrane and reading its code often see things the maintainers don't. We'd rather hear from you than not. > [!IMPORTANT] > The authoritative process lives in the repository's `CONTRIBUTING` file and `LICENSE`. > This page summarises them; if anything here and those files disagree, the files win. Read > [licensing](./licensing.md) before you contribute, because your contributions are licensed > under the project's terms. ## Before you start - *Set the project up locally.* Follow [self-hosting](./self-hosting.md) for the dev container and `mprocs`, or the deeper [internal local-development guide](../developer-internal/local-development.md). - *For anything non-trivial, open an issue first.* A short discussion before you write code saves everyone time and avoids a PR that has to be rewritten. ## What gets prioritised *Security and privacy pull requests are prioritised.* dembrane handles people's spoken words - often sensitive, often personal - so anything that improves security posture, fixes a data leak, or strengthens privacy guarantees jumps the queue. If your PR is in this category, say so in the description. ## Pull-request requirements A PR is much more likely to be merged quickly if it arrives complete: - *Tests.* Cover the behaviour you changed. New features need new tests; bug fixes need a test that fails before your change and passes after. - *Style.* Match the existing code style and pass the project's linters and formatters (`uv`-managed Python on the backend, `pnpm`-managed TypeScript on the frontend). - *Docs.* If you change behaviour, configuration, or an endpoint, update the relevant documentation in the same PR. A feature without docs is half-finished. Keep PRs focused - one logical change per PR is far easier to review than a sprawling one. ## The Contributor Licence Agreement (CLA) dembrane requires a *CLA*. By contributing, you grant *Dembrane B.V.* a perpetual licence over your contributions. This is what lets the project ship your code under both the open BSL 1.1 licence and the commercial licence (and re-licence to GPLv3 on each release's Change Date, as described in [licensing](./licensing.md)). You'll be prompted to accept the CLA as part of the contribution process; we can't merge contributions without it. ## Code of conduct dembrane has a *code of conduct*, and it applies everywhere the community gathers - issues, pull requests, and the Slack. The short version: be decent, be respectful, assume good faith, and make space for people who are new. The full text is in the repository. ## Reporting a security issue > [!WARNING] > *Do not open a public issue or PR for a security vulnerability.* Disclosing it publicly > before it's fixed puts every dembrane user at risk. Report security issues privately to *sameer@dembrane.com*. Include enough detail to reproduce, and give us a reasonable window to fix and ship before any public disclosure. Security and privacy fixes are prioritised, as noted above. ## Community Slack There's a *community Slack* for questions, discussion, and help getting set up - a good place to float an idea before you write code, or to ask why something works the way it does. The invite link is in the project configuration (and surfaced in the dashboard); the maintainers and other contributors hang out there. ## Where to dig deeper If you're going to work on the codebase in earnest, the [internal developer guides](../developer-internal/index.md) are written for exactly that: - [Architecture](../developer-internal/architecture.md) - how the services fit together. - [The data model](../developer-internal/data-model.md) - the Directus collections. - [The processing pipeline](../developer-internal/processing-pipeline.md) - transcription through to reports. - [Deployment & releases](../developer-internal/deployment-and-releases.md) - how changes ship. ## Related - [Licensing](./licensing.md) - BSL 1.1, the Change Date, and the CLA's purpose. - [Self-hosting](./self-hosting.md) - getting it running locally. - [Building on dembrane (overview)](./index.md). - [Internal developer overview](../developer-internal/index.md). --- # Architecture dembrane is event-driven and split into several long-running processes that talk to each other through Postgres, Redis/Valkey and S3. This page is the map: what runs where, how the API is layered, and how a request is authenticated. For the build-and-run mechanics see [local development](./local-development.md); for how the model fans out into background work see [the processing pipeline](./processing-pipeline.md). ## The services and their ports | Service | Default port | Code | What it does | |---|---|---|---| | FastAPI backend | `:8000` | `echo/server/dembrane/` | The HTTP API (v1 + v2), the BFF, and the service layer. | | Agent service | `:8001` | `echo/agent/` | Agentic chat (CopilotKit + LangGraph). Leased turns in Redis. | | Directus | `:8055` | `echo/directus/` | Data layer, authentication, file storage. 49 collections. | | Dramatiq `network` workers | - | `echo/server/dembrane/tasks.py` | gevent workers for async I/O: transcribe, merge, summarise, reports, emails. | | Dramatiq `cpu` workers | - | `tasks.py` | CPU-bound work (e.g. chunk merge). Single-threaded. | | APScheduler | - | `echo/server/dembrane/scheduler.py` | Blocking scheduler; fans periodic work out to Dramatiq. | | Admin dashboard (dev) | `:5173` | `echo/frontend/` | Vite dev server for the host dashboard. | | Participant portal (dev) | `:5174` | `echo/frontend/` | Vite dev server for the portal (same codebase). | Backing stores: - *PostgreSQL* with the *pgvector* extension - the system of record (managed through Directus) plus vector embeddings for retrieval. - *Redis/Valkey* - the Dramatiq broker, idempotency locks and coordination counters, SSE pub/sub, the agent's turn leases, and caches. - *S3* - audio chunks and generated files. MinIO locally, DigitalOcean Spaces in production (any S3-compatible endpoint works). The `mprocs.yaml` at the repo root launches the host processes (`server`, `workers`, `workers-cpu`, `scheduler`, `admin-dashboard`, `participant-portal`); the devcontainer's compose file runs the infra (Postgres, Redis, Directus). See [local development](./local-development.md). ## One frontend, two surfaces `echo/frontend/` is a single React/TypeScript SPA that serves both the *host dashboard* (`dashboard.dembrane.com`) and the *participant portal* (`portal.dembrane.com`). It chooses which router to mount by hostname. The dashboard is the authenticated host experience; the portal is the unauthenticated participant experience (no account needed). In dev they're two Vite servers (`:5173` and `:5174`) so you can work on either in isolation. ## The API: v1 and v2 The backend exposes two generations of API under `echo/server/dembrane/api/`: - *v1* - `/api/*`, the original routers (`api/api.py`, `conversation.py`, `project.py`, `chat.py`, `participant.py`, `project_webhook.py`, `search.py`, …). Still very much live: the participant upload API, webhooks, export and the legacy dashboard calls all sit here. - *v2* - `/api/v2/*`, under `api/v2/`. This is where the modern, role-and-billing-aware surface lives: `auth.py`, `orgs.py`, `workspaces.py`, `projects.py`, `invites.py`, `billing.py`, `admin.py` (+ `admin_managed.py`, `admin_training.py`), `onboarding.py`, `notifications.py`, `workspace_settings.py`, and more. New work generally lands in v2. v1 endpoints are kept where clients (the portal, webhooks, the iOS app's upload path) still depend on them. ### The BFF layer - `api/v2/bff/` The *backend-for-frontend* layer (`api/v2/bff/`) exists to give the dashboard and the iOS app exactly the shapes they need, composed server-side, rather than making them stitch together several primitive calls. It currently covers: - `bff/conversations.py` - conversation list/detail views shaped for the UI. - `bff/chats.py` - chat sessions and messages. - `bff/reports.py` - report views. - `bff/tags.py` - project tags. - `bff/_access.py` - the shared access-check helper the BFF endpoints lean on. > [!NOTE] > dembrane Go (iOS) calls the same `v2/bff/*` endpoints as the web dashboard, plus the v1 > `participant/*` upload API. Keep BFF responses stable - two clients depend on them. See > [dembrane Go (the mobile app)](../../features/mobile-app-dembrane-go.md). ### The service layer - `service/` Business logic that's shared across routers lives in `echo/server/dembrane/service/` (`agentic.py`, `chat.py`, `conversation.py`, `file.py`, `project.py`, `webhook.py`). Routers stay thin; the service layer holds the rules so v1, v2 and BFF endpoints behave consistently. Above that sit module-level helpers - `policies.py`, `seat_capacity.py`, `inheritance.py`, `billing_account.py`, `coordination.py`, `summary_utils.py`, and so on. ## Authentication Auth is delegated to *Directus*. The backend validates the Directus JWT on each request via `echo/server/dembrane/api/dependency_auth.py`: - `require_directus_session(request)` reads the token from either the `directus_session_token` cookie* (browser sessions) or an `Authorization: Bearer ` header (the iOS app, API clients). It decodes the JWT into a `DirectusSession`. - The decoded token carries an `admin_access` claim. When `true`, the caller is dembrane *staff* (a Directus administrator) - this is the gate for the admin panel and the staff-only endpoints in `admin.py` / `admin_managed.py` / `admin_training.py`. See [the staff guides](../staff/admin-panel-overview.md). - `require_directus_client(...)` hands a router an authenticated Directus client when it needs to read or write the data layer as the caller. Authorisation *beyond* "is this a valid user / is this staff" is policy-based, not role-based: enforcement code calls `has_policy(...)`, never checks the role string directly. That whole system - org/workspace role presets, tier gates, seats, inheritance - is covered in [roles & policies in code](./roles-and-policies.md). For the conceptual model see [roles & permissions](../../features/roles-and-permissions.md). > [!IMPORTANT] > The cookie name is configurable (`settings.directus.session_cookie_name`). Don't hard-code > `directus_session_token`; read it from settings. ## How a request flows A typical authenticated dashboard request: 1. The SPA calls a `v2/bff/*` endpoint with the session cookie. 2. `dependency_auth` validates the JWT and resolves the caller (and whether they're staff). 3. The router calls the service layer, which checks `has_policy(...)` for the action and reads/writes through Directus (or, for hot reads, pgvector/SQL). 4. Anything slow or fan-out-shaped (transcription, summaries, reports, emails) is *not* done inline - the router enqueues a Dramatiq actor and returns. Progress streams back to the client over SSE, backed by Redis pub/sub. See [the processing pipeline](./processing-pipeline.md) and [background jobs](./background-jobs-and-scheduler.md). ## The standalone agent service Agentic chat does *not* run inside the FastAPI process. It's a separate service in `echo/agent/` (port `:8001`) built on CopilotKit + LangGraph, with its own settings and an `echo_client.py` that calls back into the backend for data. It coordinates turns with *leases in Redis* so a run isn't processed twice. Standard (non-agentic) chat *is* served by the main backend. The split, the tools, and the lease runtime are covered in [chat & the agent service](./chat-and-agent.md). ## Production note The production API runs under a *custom asyncio uvicorn worker* (`dembrane.asyncio_uvicorn_worker.AsyncioUvicornWorker`) - we avoid `uvloop` for `nest_asyncio` compatibility. Locally, `mprocs` runs uvicorn with `--loop asyncio --reload`. --- *Related* - [The data model](./data-model.md) - [The processing pipeline](./processing-pipeline.md) - [Background jobs & scheduler](./background-jobs-and-scheduler.md) - [Roles & policies in code](./roles-and-policies.md) - [Authentication (external)](../developer-external/authentication.md) --- # The processing pipeline This is the heart of dembrane: how raw audio becomes a clean, summarised, queryable conversation. It's an event-driven fan-out - work is split into per-chunk tasks on the Dramatiq `network` queue, coordinated through Redis counters, and joined back up when the last chunk lands. The tasks live in `echo/server/dembrane/tasks.py`; the coordination lives in `echo/server/dembrane/coordination.py`. Read [background jobs & scheduler](./background-jobs-and-scheduler.md) alongside this - that page covers the queues, the gevent rules, and the catch-up jobs that backstop the pipeline. ## The happy path, end to end ``` upload chunk → S3 (presigned) → task_transcribe_chunk (Gemini 2.5 Pro via Vertex AI, or LiteLLM fallback) → decrement pending-chunks counter … when counter hits 0 AND conversation is finished: → task_finalize_conversation ├─ task_merge_conversation_chunks (cpu queue) └─ task_summarize_conversation (Gemini) ``` ### 1. Upload to S3 Audio arrives in chunks (≈30 s each). The participant portal and the iOS app request a presigned URL (`POST /api/participant/conversations/{cid}/get-upload-url`, rate-limited 40/min), upload the chunk straight to S3, then confirm. A `conversation_chunk` row is created. See [the participant API](../developer-external/participant-api.md). When chunks are created for transcription, the pipeline *increments a Redis pending-chunks counter* for the conversation (`increment_pending_chunks`). ### 2. Transcribe - `task_transcribe_chunk` (priority 0, `network`) Each chunk is transcribed independently. Two backends: - *Gemini Vertex AI EU* - The chunk audio is transcribed directly on Gemini 2.5 Pro (via `MULTI_MODAL_PRO`) deployed in Google Cloud Vertex AI `europe-west1` (EU) region using the `transcript_from_audio_workflow` prompt workflow. This single-pass workflow performs transcription, hotword normalisation, and optional PII redaction. This guarantees that all audio data and processing remain strictly within EU boundaries while dramatically reducing transcription latency. The output (corrected transcript and note only) is stored in the chunk's `diarization` field under schema `Dembrane-26-07-gemini`. Note that word-level timestamps and speaker labelling are not returned. - *LiteLLM* - The fallback multimodal translation and transcription path, routed through the `MULTI_MODAL_*` model groups when required. The "key terms" / hotwords come from the project's `default_conversation_transcript_prompt` field (set in [the portal editor](../../features/portal-editor.md)). When a chunk finishes (success or recoverable error) the pipeline *decrements* the pending-chunks counter, guarded so a single chunk can only decrement once (`_chunk_decremented_key`). ### 3. Finalize - `task_finalize_conversation` (priority 20, `network`) When the pending-chunks counter reaches *0* *and* the conversation is marked finished, the conversation is finalised. This step is *idempotent*: it takes a Redis finalize lock (`mark_finalize_in_progress`) so two workers racing on the last chunk don't both finalise. Finalize dispatches the join steps. ### 4. Merge - `task_merge_conversation_chunks` (priority 10, `cpu`) The CPU-bound step: stitch the per-chunk transcripts into the full conversation transcript. This runs on the `cpu` queue (single-threaded) rather than `network`, because it's compute-bound, not I/O-bound. It stores its result (`store_results=True`). ### 5. Summarise - `task_summarize_conversation` (priority 30, `network`) A Gemini pass that produces the conversation summary. Completion is signalled by `summary` becoming non-null - that's the single source of truth for "summarisation done", which the catch-up job keys off. There's a finish hook (`task_finish_conversation_hook`) and webhook dispatch (`conversation.transcribed`, `conversation.summarized`) layered on top - see [webhooks](../developer-external/webhooks.md). ## Coordination & idempotency (Redis) Because the last-chunk join is a race, the pipeline leans on Redis keys under the `coord:` prefix (`coordination.py`): | Key | Purpose | |---|---| | `coord:pending_chunks:{cid}` | The fan-in counter. Hits 0 → trigger finalize. 24 h TTL. | | `coord:processing_started:{cid}` | One-shot flag that processing has begun. | | `coord:finalize_in_progress:{cid}` | Lock so only one worker finalises. ~5 min TTL. | | `coord:finish_in_progress:{cid}` | Lock around the finish hook. | | `coord:chunk_decremented:{cid}:{chunk_id}` | Guard so a chunk decrements the counter exactly once. | > [!IMPORTANT] > These counters can drift (a worker dies mid-task, a webhook is missed). That's why > scheduled *catch-up / reconcile* jobs exist - `task_collect_and_finish_unfinished_conversations` > (every 2 min), `task_reconcile_transcribed_flag` (every 3 min), and > `task_catch_up_unsummarized_conversations` (every 5 min). Fix root causes in the pipeline, > not symptoms in the catch-up jobs (see `echo/server/AGENTS.md`). The catch-up jobs are a > safety net, not the mechanism. The flag invariants worth memorising: - `is_finished` - the user/system marked the conversation done. - `is_all_chunks_transcribed` - ready for summarisation (true for *audio and text* conversations). - `summary != null` - summarisation complete. ## Reports - two-phase Report generation is a fan-out/fan-in of its own: 1. *Phase 1 - summarise.* `task_create_report` fans out per-conversation summarisation, then `task_report_summarization_done` signals when that's complete. 2. *Phase 2 - generate.* `task_create_report_continue` composes the multi-section report from the gathered summaries. Scheduled reports are dispatched by `task_check_scheduled_reports` (every 5 min); notification recipients come from `project_report_notification_participants`. See [reports](../../features/reports.md). ## Chat retrieval modes Chat doesn't re-read everything every time. It has two retrieval modes: - *overview* - works over conversation *summaries*. Cheaper, broad, good for "what came up across all of this?". - *deep_dive* - works over full *transcripts* for the selected conversations. More expensive, precise. Embeddings (pgvector) back retrieval; the LangGraph agent service adds tool-driven search on top. See [chat & the agent service](./chat-and-agent.md). ## Live progress - SSE over Redis pub/sub The pipeline doesn't poll the database to drive the UI. Progress is *published to Redis* and *streamed to clients over Server-Sent Events* (`stream_status.py`, `processing_status_utils.py`). A worker publishes a status event; the FastAPI SSE endpoint, subscribed to the conversation's Redis channel, relays it to the dashboard or the iOS app. This keeps workers and the API decoupled - workers never hold an HTTP connection to a client. ## The LLM layer - LiteLLM Router All model calls go through a *LiteLLM Router* (`llm_router.py`) configured by model group. The router load-balances and fails over across multiple deployments per group, with weight inferred from the env-var suffix (primary = 10, `_1` = 9, `_2` = 8, …): | Group | Used for | Audio | |---|---|---| | `MULTI_MODAL_PRO` (Gemini 2.5 Pro) | Chat, reports, Get-Reply replies, artifact generation | Yes | | `MULTI_MODAL_FAST` (Gemini Flash) | Realtime verification | Yes | | `TEXT_FAST` | Summaries, chat streaming, auto-select | No | Configure with `LLM____*` (and numbered fallbacks `LLM___1__*`). The full reference is `echo/docs/litellm_config.md`; for the operator's view see [configuration & LLM providers](../developer-external/configuration-and-llm-providers.md). > [!NOTE] > Built-in analysis (the Gemini-powered summaries, library, chat-with-analysis) is a > *Changemaker+* capability. *Innovator* workspaces get bring-your-own-LLM via MCP > instead (*coming soon*). Free workspaces have a 1-hour recording cap and the over-cap > machinery (ADR 0001). See [tiers & billing](../../features/tiers-and-billing.md). ## EU data residency Transcription and the language models can be pinned to EU regions: Vertex `europe-west*`, an EU S3 endpoint, and EU SendGrid. The `Guardian` tier's sovereign stack builds on this (*coming soon*). See [self-hosting](../developer-external/self-hosting.md). --- *Related* - [Background jobs & scheduler](./background-jobs-and-scheduler.md) - [Chat & the agent service](./chat-and-agent.md) - [The data model](./data-model.md) - [Transcription (feature)](../../features/transcription.md) - [The participant API](../developer-external/participant-api.md) --- # The data model dembrane's system of record is *Directus* on PostgreSQL - 49 collections. The schema is versioned in `echo/directus/sync/snapshot/` (collections, fields, relations as JSON), managed with `directus-sync`. This page maps the collections you'll work with day to day and how they hang together. For how data is *created and processed* see [the processing pipeline](./processing-pipeline.md); for how access to it is decided see [roles & policies in code](./roles-and-policies.md). > [!NOTE] > The snapshot under `echo/directus/sync/snapshot/collections/` is the source of truth for > the schema. When you add or change a collection, update the snapshot and follow > [database migrations](./deployment-and-releases.md) - pushing schema to prod has sharp > edges (the `is_indexed` pitfall, drop-index ordering). ## The spine: org → workspace → project → conversation The core hierarchy, top to bottom: ``` org └─ workspace (an org has many workspaces) └─ project (a workspace has many projects) └─ conversation (a project collects many conversations) └─ conversation_chunk (a recording arrives as chunks) ``` Each level carries its own membership and settings, and access is computed by walking this spine plus the inheritance rules (see below and [roles & policies](./roles-and-policies.md)). ### Organisation - `org` - the top-level tenant. Carries `is_partner` (a [partner](../../features/partner-program.md) hosts external-client workspaces) and the org's branding/billing defaults. - `org_membership` - who belongs to an org and at what role (`member` / `admin` / `billing` / `owner`). Org membership is *independent* of workspace membership (ADR 0004): you can be an org member with no workspaces, or be in a workspace as `external`/`observer` with no org membership. - `org_invite` - pending org-level invitations. ### Workspace - `workspace` - the unit most hosts live in. Holds `visibility` (`open_to_organisation` / `invite_only` / `private`), `usage_context` (`external` marks an external-client workspace), `data_owner_email` / `data_owner_org_name`, whitelabel logo, and tier/billing pointers. - `workspace_membership` - direct membership rows with a stored `role` (`owner` / `admin` / `member` / `billing` / `external` / `observer`). `external` is a stored role, not a boolean (ADR 0003). Effective membership also folds in org-admin/member inheritance - see `inheritance.py`. - `workspace_invite` - pending workspace invitations (email + role + hash URL, 7-day expiry); also used for invite-by-link. - `workspace_request` - free-tier upgrade requests (kinds `new_workspace` and `tier_upgrade`); the staff approve/deny flow reads these. See [upgrade requests](../staff/upgrade-requests.md). ### Project - `project` - name, language, visibility, the conversation toggle, participant-name settings, and the *portal editor* fields, including `default_conversation_transcript_prompt` (the "key terms" that improve transcription). See [the portal editor](../../features/portal-editor.md). - `project_membership` - per-project sharing for private projects (Innovator+), with project-level roles `viewer` / `editor`. - `project_tag` - tags defined on a project; the join `conversation_project_tag` attaches them to conversations. - `project_webhook` - webhook subscriptions (Changemaker+). See [webhooks](../developer-external/webhooks.md). ### Conversation - `conversation` - a single contribution: an audio recording or a piece of text. Carries the processing flags (`is_finished`, `is_all_chunks_transcribed`, `summary`), source, and over-cap stamping. - `conversation_chunk` - the unit of recording and transcription. Audio arrives in chunks (≈30 s); each is uploaded to S3 and transcribed independently. - `conversation_segment` + `conversation_segment_conversation_chunk` - diarised/structured segments and their link to the chunks they came from. - `conversation_reply` - replies in the "Get Reply" audio-replay flow. - `conversation_artifact` - verified artifacts extracted during the participant verification flow. - `conversation_link` - links between conversations. ## Chat - `project_chat` - a chat session scoped to a project (and a selection of conversations as context). - `project_chat_message` - the messages in a session. - `project_chat_conversation` / `project_chat_message_conversation` - joins recording which conversations are in a chat's context and which were cited by a given message (the "sources"). Standard versus agentic chat is covered in [chat & the agent service](./chat-and-agent.md). ## Reports - `project_report` - a generated multi-section report. - `project_report_metric` - metrics attached to a report. - `project_report_notification_participants` - who gets emailed when a scheduled report is generated. Reports are produced in two phases (fan-out summaries → generate). See [the processing pipeline](./processing-pipeline.md). ## Agentic runs - `project_agentic_run` - a run of the agent service against a project's data. - `project_agentic_run_event` - the event stream for a run (tool calls, progress, results), the durable record behind the live SSE feed. ## Library & analysis - `view` - a custom analysis view over a project's conversations. - `aspect` + `aspect_segment` - AI-extracted aspects/topics and the segments that support them. - `insight` - extracted insights. - `project_analysis_run` - a run of the library/analysis generation. These power the [library & analysis](../../features/library-and-analysis.md) surface (Changemaker+). ## Billing, tiers and seats - `billing_account` - the billing unit. Can be *org-scoped* (pooled across the org's workspaces) or *workspace-scoped* (external-client). Drives tier, Mollie subscription, discounts and managed/offline invoicing. See `billing_account.py` and [tiers & billing](../../features/tiers-and-billing.md). - `referral_ledger` - partner kickback/discount deals (kickback %, discount %, EUR cap, expiry). Seats are computed, not stored as a count: `seat_capacity.py` derives the effective seat state from membership rows. See [roles & policies in code](./roles-and-policies.md). ## People, trainings and verification - `app_user` - the application-side user record (alongside Directus's own `directus_users`). - `training` + `training_license` - compliance trainings (online / in_person / flex) and the 1-year licences they grant. See [trainings & licences](../staff/trainings-and-licences.md). - `verification_topic` (+ `verification_topic_translations`) - the topics a participant verifies against in the portal verification flow. - `prompt_template` - reusable chat/analysis prompt templates (built-in + user templates). ## Cross-cutting - `processing_status` - per-conversation processing state used to render progress and drive catch-up/reconcile jobs. See `processing_status_utils.py` and [background jobs](./background-jobs-and-scheduler.md). - `notification` - in-app notifications (the email-digest batching reads from here). - `announcement` (+ `_translations`, `_activity`) - product announcements shown in-app. - `access_request` - requests to join a workspace (the org-admin discovery flow). - `languages` - supported language reference data. ## How access is derived (not stored) A user's effective role in a workspace is *computed*, not just read from a row. `inheritance.py` folds together: their direct `workspace_membership` row, org-admin auto-join (gated by the workspace's `visibility`), org-member inheritance, and sticky-removal records. The result feeds `policies.py`, which expands the role into a policy set and checks the requested action with `has_policy(...)`. So when debugging "why can this person see this?", trace `inheritance.derive_workspace_role` → `policies.get_effective_policies`, don't just look at the membership table. --- *Related* - [Architecture](./architecture.md) - [Roles & policies in code](./roles-and-policies.md) - [The processing pipeline](./processing-pipeline.md) - [Database migrations & deployment](./deployment-and-releases.md) --- # Chat & the agent service dembrane has two ways to "talk to your data": *standard chat* (retrieval-augmented generation served by the main backend) and *agentic chat* (a tool-using agent that runs in a separate service). This page explains the split, the agent service in `echo/agent/`, the tools it exposes, and how turns are coordinated with Redis leases. For the conceptual feature view see [chat & ask](../../features/chat-and-ask.md); for retrieval and model groups see [the processing pipeline](./processing-pipeline.md). ## Standard chat vs agentic chat | | Standard chat | Agentic chat | |---|---|---| | Where it runs | Main FastAPI backend (`:8000`) | Standalone agent service (`:8001`) | | How it works | RAG over a selected set of conversations - retrieve, then answer | A LangGraph agent that calls *tools* to decide what to read, iterating until it can answer | | Retrieval mode | `overview` (summaries) or `deep_dive` (transcripts) | Tool-driven: lists conversations, keyword-searches, pulls transcripts on demand | | Toggle | Default chat mode | "Agentic mode" in the chat UI | | State | `project_chat` + `project_chat_message` | `project_agentic_run` + `project_agentic_run_event` (plus the chat tables) | Both are scoped to a *project* and a selection of conversations as context. The "sources" a message cites are recorded through the `project_chat_message_conversation` join. Standard chat's two retrieval modes - `overview` over summaries, `deep_dive` over full transcripts - are covered in [the processing pipeline](./processing-pipeline.md#chat-retrieval-modes). ## Why the agent is a separate service `echo/agent/` is intentionally isolated (see its `README.md`): - It keeps agent execution *out of the frontend runtime*. - It *avoids dependency conflicts* with `echo/server` (CopilotKit/LangGraph pull in their own stack). - It supports *long-running execution* with a *backend-owned run lifecycle* - the agent does the thinking, but auth, persistence and notifications stay with the `echo/server` gateway. It exposes a tiny surface: - `GET /health` - `POST /copilotkit/{project_id}` - the CopilotKit endpoint the run flows through. It builds its graph in `echo/agent/agent.py` (a LangGraph `StateGraph` over `CopilotKitState`) and reads project data via `echo/agent/echo_client.py`, which calls back into the backend. Auth is handled in `echo/agent/auth.py`. ## The tools The agent's graph (`create_agent_graph` in `agent.py`) binds twenty tools. The model is nudged to get an overview first, then narrow: - *Conversations*: `listProjectConversations` (the inventory - start here), `findConvosByKeywords` (keyword search; the prompt steers toward 2-4 focused keywords, with a guardrail against low-signal and repeated searches), `listConvoSummary`, `listConvoFullTranscript`, `grepConvoSnippets`. - *Documentation*: `listDocs`, `readDoc(paths)`, `grepDocs(patterns)` (both take lists so lookups batch into one step), `readSkill` - the agent answers "how do I" questions from the published docs corpus and cites the page. - *Project settings*: `getProjectSettings`, `proposeProjectUpdate`, `proposeCustomVerificationTopic` - the agent never writes settings; proposals render as review cards the host applies or rejects. - *Chats*: `listProjectChats`, `readChat` - earlier chats in the project, excluding other members' private ones. - *Live status*: `getLiveConversationStatus` - the same snapshot as the host Monitor page (shared `gather_project_monitor`). - *Support*: `reachOutToDembrane` - writes a `support_request` outbox row; the prompt forbids promising follow-up and requires honest failure reporting. - *Memory*: `readMemory`, `remember(scope, content, memory_key)` - one `agent_memory` collection with `workspace | project | user` scopes (user scope is the only one that may hold personal detail). Writes upsert on `memory_key`. Hosts view + delete (never edit) via `/v2/bff/memory/*` and the settings surfaces. - *Progress*: `sendProgressUpdate` - emit a progress event so the UI can show what the agent is doing mid-run. The first user message carries `Project Name`, `Workspace Context` (the host-written `workspace.context` field), and `Project Context` as standing guidance. The graph guards against runaway loops (counting tool calls since the last assistant update, nudging the model to answer from gathered evidence rather than searching forever), and the prompt bans exposing internal machinery (tool names, JSON) to the host. ## The lease-based turn runtime Agentic runs are long and resumable, so the backend owns the lifecycle and uses *Redis leases* to make sure a turn is processed exactly once. The runtime primitives are in `echo/server/dembrane/agentic_runtime.py`; the worker that drives a run is `echo/server/dembrane/agentic_worker.py` (`process_agentic_run`). Keys are namespaced under `agentic:run:{run_id}:turn:{turn_seq}:…`: | Helper | Key | Purpose | |---|---|---| | `acquire_turn_lease` / `refresh_turn_lease` / `release_turn_lease` | `…:lease` | A TTL'd lease an owner holds while processing a turn. Acquire is atomic; refresh/release use a Lua check-and-act so only the owner can extend or drop it. | | `request_cancel` / `is_cancel_requested` / `clear_cancel` | `…:cancel` | Cooperative cancellation - the worker checks `_raise_if_cancelled` between steps and bails cleanly. | | `publish_live_event` / `subscribe_live_events` / `read_live_event` | `agentic:run:{run_id}` channel | The live event stream over Redis pub/sub, relayed to the client over SSE. | So a turn's life is: acquire the lease → run the LangGraph step, appending events to `project_agentic_run_event` and publishing them live → periodically refresh the lease and check for cancellation → on completion persist the assistant message to the chat and release the lease. Because the lease has a TTL, a worker that dies frees the turn for another to pick up, without double-processing. > [!NOTE] > The durable record (`project_agentic_run_event`) and the live pub/sub stream carry the same > events. The DB rows let a client that reconnects rebuild history; the pub/sub stream gives a > connected client low-latency updates. Don't rely on pub/sub alone - a missed message must be > recoverable from the event rows. ## How a run flows 1. The dashboard opens an agentic chat; the backend creates a `project_agentic_run`. 2. A turn is enqueued; the agentic worker acquires the *turn lease* and starts driving the LangGraph. 3. The agent calls tools (`listProjectConversations`, `findConvosByKeywords`, transcript pulls), each tool result and progress update appended as a `project_agentic_run_event` and published live. 4. The worker refreshes the lease while it works and checks for cancellation between steps. 5. On finish, the assistant message is persisted to `project_chat_message` and the lease released. 6. The client renders the stream over SSE, backed by the Redis channel. ## Models The agent runs on Gemini (its `_build_llm` constructs a `ChatGoogleGenerativeAI`; set `GEMINI_API_KEY`). The main backend's chat goes through the LiteLLM Router groups - `TEXT_FAST` for streaming, `MULTI_MODAL_PRO` for richer turns. See [the processing pipeline](./processing-pipeline.md#the-llm-layer-litellm-router). ## Tiers Built-in chat-with-analysis (the Gemini path) is *Changemaker+*. *Innovator* replaces the built-in analysis with bring-your-own-LLM via MCP - connect ChatGPT/Claude - which is *coming soon* (gated on MCP shipping). Free-tier chat is gated. See [tiers & billing](../../features/tiers-and-billing.md) and [MCP & bring-your-own-LLM](../developer-external/mcp-and-byo-llm.md). --- *Related* - [Architecture](./architecture.md) - [The processing pipeline](./processing-pipeline.md) - [The data model](./data-model.md) - [Chat & Ask (feature)](../../features/chat-and-ask.md) --- # Roles & policies in code Access control in dembrane is *policy-based, not role-based*. A *role* is a display label; the enforcement source of truth is a *policy set*. Enforcement code always asks "does this caller hold this policy?" - never "is this caller an admin?". This page is the engineer's view of `echo/server/dembrane/policies.py` and the modules around it. For the conceptual model (what each role can do, told plainly) see [roles & permissions](../../features/roles-and-permissions.md). > [!IMPORTANT] > The pattern is AWS-IAM-inspired: presets are hardcoded in `policies.py`; the database stores > only `custom_policies` (extras *beyond* the preset). Effective policies = > `preset[role] + custom_policies`. Enforcement code calls `has_policy(...)`. If you find code > branching on a raw role string for an access decision, that's a bug - route it through a > policy. ## The presets `policies.py` defines three preset dictionaries: - `ORG_ROLE_PRESETS` - org-level. `member` (`org:view`), `admin` (manage users/settings/billing, create + view workspaces, view usage), `billing` (financial visibility across all workspaces - no invite/create/settings), `owner` (`["*"]`). - `WORKSPACE_ROLE_PRESETS` - the workspace roles, the backbone of the product. `owner` (`["*"]`), `admin` (full project/content/member/settings/billing), `member` (author: read/create/update projects, delete conversations, chat, generate + publish reports, view usage), `billing` (financial only), `external` (a paid outside collaborator - read/update projects, read conversations, chat, view + generate reports), `observer` (free, read-only - read projects/conversations, view reports). - `PROJECT_ROLE_PRESETS` - for private-project sharing (Innovator+). `viewer` and `editor`. Each preset is an explicit allowlist. Anything not listed is implicitly denied. So `external` deliberately lacks `workspace:view_usage`, `member:invite`, `report:publish`, `project:create`, `conversation:delete`; `observer` deliberately lacks `chat:use`, `report:generate`, `project:update` - hitting that wall is the observer→external upgrade trigger. ## The functions you'll call ```python get_effective_policies(role, custom_policies=None, presets=WORKSPACE_ROLE_PRESETS) -> list[str] has_policy(role, custom_policies, required, presets=..., workspace_tier=None) -> bool meets_tier(current_tier, minimum_tier) -> bool ``` - `get_effective_policies` expands a role into its policy list (preset + custom), normalising any legacy role first. - `has_policy` is the one enforcement code calls. It returns `True` when the role's effective policies contain `"*"` or the `required` policy - *and*, if `workspace_tier` is passed and the policy is tier-gated, the tier check rides along automatically. - `meets_tier` compares against `TIER_ORDER = ["free", "innovator", "changemaker", "guardian"]`. ### Tier gates ride along with the policy check `TIER_REQUIRED_FOR_POLICY` maps policies to the minimum tier required: | Policy | Minimum tier | |---|---| | `workspace:export`, `project:share`, `workspace:set_private`, `project:set_private` | innovator | | `workspace:whitelabel`, `workspace:api_access`, `workspace:webhooks` | changemaker | Because `has_policy` enforces this when you pass `workspace_tier`, an endpoint usually only needs *one* call - the tier gate is not a separate check. Pass the workspace tier and the gate is automatic; omit it (e.g. in tests) to bypass. ## Role hierarchy - escalation guard `ROLE_HIERARCHY` orders the workspace roles for *escalation prevention*, not capability: ``` observer(0) < external(1) < member(2) < billing(3) < admin(4) < owner(5) ``` The invite endpoint (and any future role-change endpoint) uses this so a caller can only grant a role *at or below their own* level. It is *not* a capability ranking - `billing` sits above `member` here despite having no content access, because the number is about "what you're allowed to hand out", not "what you can do". See ADR 0003. ## Staff policies `STAFF_POLICIES` is a finer grain than "any Directus administrator": `staff:can_set_tier`, `staff:can_set_visibility`, `staff:can_transfer`. Today the staff gate is the JWT `admin_access` claim (see [architecture](./architecture.md#authentication)); the named staff policies are wiring-in-progress reference for when a storage mechanism lands. Treat them as the future seams for splitting up staff power. ### The admin panel API The staff panel (`/admin`, `AdminSettingsRoute`) is server-gated: every route below re-checks `admin_access`, so it can't be reached by guessing a URL. The [staff guide](../staff/index.md) covers what each action does in plain terms; this is the route map behind it. | Action | Endpoint | Extra staff policy | |---|---|---| | Usage & billing rollup | `GET /api/v2/admin/billing-rollup` (`?month_offset=` for the 12-month lookback) | - | | At-risk inbox | `GET /api/v2/admin/at-risk` | - | | Payments view | `GET /api/v2/admin/payments` (actions in `admin_managed.py`) | - | | Change tier | `PATCH /api/v2/workspaces/{id}/tier` | `staff:can_set_tier` | | Discount | `PATCH /api/v2/admin/workspaces/{id}/discount` | - | | Grant reverse trial | `POST /api/v2/admin/billing-accounts/{id}/grant-trial` | - | | Change admin | `POST /api/v2/admin/workspaces/{id}/change-admin` | - | | Reset usage | `POST /api/v2/admin/workspaces/{id}/reset-usage` (requires a reason) | - | | Partner toggle | `PATCH /api/v2/admin/orgs/{id}/partner` | - | | Referral ledger | `GET /api/v2/admin/referral-ledger` | - | | External-led orgs | `GET /api/v2/admin/external-led-orgs` | - | | Set workspace visibility | (workspace visibility change) | `staff:can_set_visibility` | | Transfer workspace | (owner handoff) | `staff:can_transfer` | ## Seats - `seat_capacity.py` Seats are *computed from membership rows*, never stored as a count. The billable roles are: ```python _SEAT_ROLES = {"owner", "admin", "member", "billing", "external"} ``` `observer` is deliberately absent - it's free. Key functions: - `effective_seat_user_ids(workspace_id)` - the set of users that count toward seats in one workspace. - `compute_effective_seat_state(...)` - returns `(seats_used, member_count, external_count, observer_count)`. Seats are *pooled across a billing account's workspaces*, and a person counts *once per workspace*. - `count_pending_invites(workspace_id)` - pending invites count toward the cap (observer invites skip it). - `assert_can_add_seat(...)` - note: seats are *metered, never blocked*. Invites are never walled by capacity; this surfaces state and messaging, it doesn't reject. See ADR 0005. ## Membership inheritance - `inheritance.py` A user's *effective* workspace role is derived, not just read. `inheritance.py` folds together: - their direct `workspace_membership` row, - org-admin auto-join and org-member inheritance - gated by the workspace's `visibility` (`open_to_organisation` auto-joins org admins; `private` does not), - sticky-removal records (`sticky_remove` / `sticky_unremove`) so an explicitly-removed user doesn't get re-inherited. `derive_workspace_role(...)` produces the effective role; `user_can_access(workspace_id, user_id)` returns `(role, source)`. When debugging "why can this person see this?", trace `inheritance.derive_workspace_role` → `policies.get_effective_policies` → `has_policy`. Don't stop at the membership table - the answer often lives in inheritance. ## Write-time invariants Some rules are enforced when data is written, not at read time: - `external` ⟺ no `org_membership` in that org (ADR 0003). To promote external→member, an admin removes the external row, adds the user to the org, and re-invites as member. There's no in-place "convert" button - the cross-table mutation is deliberate. - `observer` only exists in external-client workspaces.* Internal workspaces reject observer invites (ADR for the free observer role; `seat_capacity` excludes observer from the seat pool). - Legacy `viewer` rows* map to `member` at read time via `_normalize_legacy_role`, which logs a warning so ops can spot and convert lingering rows. There's no migration - convert at next touch. ## How to add a capability (a new policy) 1. *Name it* with the `domain:verb` convention (`project:read`, `workspace:export`, …). 2. *Add it to the relevant preset(s)* in `policies.py` (`WORKSPACE_ROLE_PRESETS` and/or `ORG_ROLE_PRESETS`/`PROJECT_ROLE_PRESETS`) for every role that should have it. Remember: presets are allowlists - only the roles you list get it. 3. *Gate it by tier* if needed by adding an entry to `TIER_REQUIRED_FOR_POLICY`. Then any `has_policy(..., workspace_tier=...)` call enforces it for free. 4. *Enforce it* at the endpoint by calling `has_policy(role, custom_policies, "your:policy", workspace_tier=...)`. Never branch on the role string. 5. *Reflect it in the matrix* in [roles & permissions](../../features/roles-and-permissions.md) so the docs and the capability table stay true. 6. *Frontend display* is separate - `echo/frontend/src/lib/roles.ts` (`displayRole`, `roleColor`, `ROLE_HIERARCHY`) handles how roles render (observer & external render grey). Adding a policy doesn't touch this; adding a *role* does. ## How to add a role arm Adding a whole role is heavier - it touches presets, the hierarchy, seats and inheritance: 1. Add the role to the relevant `*_ROLE_PRESETS` with its allowlist. 2. Add it to `ROLE_HIERARCHY` at the right rung (this controls who can grant it). 3. Decide whether it consumes a seat - add to or omit from `_SEAT_ROLES` in `seat_capacity.py`. 4. Teach `inheritance.py` how the role interacts with org membership and visibility (e.g. the external/observer "no org_membership" invariant). 5. Wire the invite branches (`api/v2/invites.py`, `_invite_helpers.py`) and the frontend role display. 6. Write the write-time invariants and document the upgrade/downgrade path. > [!WARNING] > Roles aren't free to add. The five-role collapse (matrix v1.1) plus observer was a > deliberate simplification. Prefer a new *policy* on an existing role over a new role. > Read ADR 0003, 0004 and 0005 before proposing one. ## The ADRs that govern this - *ADR 0003* - external as a stored role (removed the `is_external` boolean; the role/org-membership invariant). - *ADR 0004* - the unified invite modal and org-only membership (org membership independent of workspace membership). - *ADR 0005* - the per-seat tier overhaul (seats, pooling, metered-not-blocked, the four tiers). They live in `echo/docs/adr/`. --- *Related* - [Roles & permissions (feature)](../../features/roles-and-permissions.md) - [Tiers & billing (feature)](../../features/tiers-and-billing.md) - [The data model](./data-model.md) - [Architecture - authentication](./architecture.md#authentication) --- # Background jobs & scheduler Anything slow or fan-out-shaped in dembrane runs as a background task, not inline in the API. Tasks are *Dramatiq actors* (`echo/server/dembrane/tasks.py`) brokered by Redis; periodic work is dispatched by *APScheduler* (`echo/server/dembrane/scheduler.py`). This page is the operational reference: the queues, the rules for writing actors safely, and the full list of scheduled jobs. It pairs with [the processing pipeline](./processing-pipeline.md), which walks the transcription fan-out in detail. ## The two queues | Queue | Runner | For | |---|---|---| | `network` | `dramatiq-gevent` (gevent, many threads) | I/O-bound work: transcription, correction, finalise, summarise, reports, webhooks, emails, all the scheduled jobs. The vast majority of actors. | | `cpu` | `dramatiq` (single thread, single process) | Compute-bound work - currently `task_merge_conversation_chunks`. Kept off the gevent pool so it doesn't starve I/O greenlets. | Locally (`mprocs.yaml`): ``` workers: uv run dramatiq-gevent --queues network --processes 1 --threads 10 dembrane.tasks workers-cpu: uv run dramatiq --queues cpu --processes 1 --threads 1 dembrane.tasks scheduler: uv run python -m dembrane.scheduler ``` In production the equivalents are `prod-worker.sh`, `prod-worker-cpu.sh` and `prod-scheduler.sh` in `echo/server/`. Actors declare their queue and priority, e.g. `@dramatiq.actor(queue_name="network", priority=0)`. Lower priority numbers run first; transcription/correction sit at `priority=0`, finalise at `20`, summarise at `30`, reports at `50`. ## The cardinal rule: NO asyncio inside actors The `network` workers run under *gevent*. You *must not* run a bare asyncio event loop inside an actor - it will conflict with gevent's monkey-patching and hang or crash. Instead use the helpers in `echo/server/dembrane/async_helpers.py`: - `run_async_in_new_loop(coro)` - run a coroutine to completion from sync actor code. This is the workhorse for calling the async Directus client / async I/O from inside a Dramatiq actor. - `run_in_thread_pool(func, *args)` - offload blocking work onto a real thread-pool thread (escapes the gevent loop when you need a true OS thread). - `safe_gather(...)` - gather coroutines on the worker's loop with optional `return_exceptions`. The helpers detect whether gevent has monkey-patched the process (`_is_gevent_patched`) and spin up a background loop on a real (un-patched) thread when needed (`_ensure_background_loop`, `_real_thread_class`). You don't normally call those directly - call `run_async_in_new_loop` / `run_in_thread_pool` and let them do the right thing. > [!WARNING] > If you write `asyncio.run(...)` or `asyncio.get_event_loop().run_until_complete(...)` inside > an actor, expect breakage. This caused a production incident where summaries and merge broke > under a shared background loop. Route async work through `async_helpers`. (See `echo/AGENTS.md` > and `echo/server/AGENTS.md`.) Note the API process itself uses a *custom asyncio uvicorn worker* and avoids `uvloop` for `nest_asyncio` compatibility - the actor rule is specifically about the gevent *worker* processes, not the API. ## The flag invariants Several actors and catch-up jobs key off three flags. There is *one source of truth per flag* - fix the flag-setting logic, don't paper over it with catch-up workarounds: - `is_finished` - the user/system marked the conversation done. - `is_all_chunks_transcribed` - ready for summarisation (true for *audio and text*). - `summary != null` - summarisation complete. ## The processing actors These drive the [pipeline](./processing-pipeline.md): | Actor | Queue / priority | Role | |---|---|---| | `task_transcribe_chunk` | network / 0 | Transcribe one chunk (Gemini Vertex AI or LiteLLM), normalize hotwords, perform optional PII redaction, and decrement the pending-chunks counter. | | `task_finalize_conversation` | network / 20 | Fan-in when the counter hits 0; idempotent via Redis lock. | | `task_merge_conversation_chunks` | *cpu* / 10 | Stitch chunks into the full transcript (`store_results=True`). | | `task_summarize_conversation` | network / 30 | Gemini summary. | | `task_finish_conversation_hook` | network / 30 | Post-finish hook (webhooks, etc.). | | `task_process_conversation_chunk` | cpu / 0 | Chunk processing. | | `task_create_view` / `task_create_project_library` | network / 50 | Library & analysis generation. | | `task_create_report` → `task_report_summarization_done` → `task_create_report_continue` | network / 50 | Two-phase report generation. | | `task_dispatch_webhook` | network | Deliver a webhook with retries. | | `task_send_invite_email` / `task_send_downgrade_email` | network | Transactional email (SendGrid HTTP, via `email.py`). | ## The scheduled jobs APScheduler is a `BlockingScheduler` pinned to *UTC* with a `MemoryJobStore`. Each job's `func` is a `*.send` reference, so the scheduler doesn't *run* the work - it *enqueues* the Dramatiq actor onto the broker and returns immediately. Defaults: `misfire_grace_time=60`, `coalesce=True` (so a job that wakes late still runs once, rather than being silently skipped - this matters on loaded hosts/WSL2). | Cron | Actor enqueued | What it does | |---|---|---| | `*/2 min` | `task_collect_and_finish_unfinished_conversations` | Catch-up: finish conversations the fan-in missed. | | `*/3 min` | `task_reconcile_transcribed_flag` | Reconcile `is_all_chunks_transcribed`. | | `*/5 min` | `task_catch_up_unsummarized_conversations` | Summarise anything finished-but-unsummarised. | | `*/5 min` | `task_check_scheduled_reports` | Dispatch due scheduled report generation. | | `:00 (hourly)` | `task_expire_workspace_tiers` | Downgrade workspaces whose `tier_expires_at` elapsed back to Free. | | `:00 (hourly)` | `task_send_tier_expiry_prewarning` | Send 3-day pre-warning emails for expiring tiers. | | `*/5 min` | `task_reconcile_pending_billing` | Activate billing accounts whose first payment cleared (missed Mollie webhook/return). | | `*/15 min` | `task_reconcile_subscription_seats` | Re-price active subscriptions to match live seat counts. | | `09:00 UTC daily` | `task_flush_email_digests` | Flush batched email-notification digests. | > [!NOTE] > The catch-up/reconcile jobs are a *safety net* for the pipeline's Redis coordination - not > the mechanism. If conversations routinely need catching up, the root cause is in the actor > flow (a missed counter decrement, a dropped webhook), not the cron. Fix it there. See > [the processing pipeline](./processing-pipeline.md#coordination-idempotency-redis). ### Billing / tier / seat reconciliation The hourly tier jobs implement the Free-tier downgrade machinery (ADR 0005, building on ADR 0001's over-cap model): `task_expire_workspace_tiers` reverts elapsed tiers and notifies; `task_send_tier_expiry_prewarning` warns 3 days out. Reverse trials granted by staff (Changemaker, 1 month) auto-revert through this path. `task_reconcile_pending_billing` and `task_reconcile_subscription_seats` keep Mollie state and seat pricing honest between webhooks. See [tiers & billing](../../features/tiers-and-billing.md) and [managed & offline billing](../staff/managed-and-offline-billing.md). ### Email digest batching Notifications are individual for the first few per day, then batched: the first 5 in 24 h go out individually, after which they're rolled into a daily digest flushed at *09:00 UTC* by `task_flush_email_digests`. The throttle logic is `email_throttle.py`; transactional sending is `email.py` (SendGrid HTTP API - note Directus's own emails use a *separate* SMTP path; don't conflate them, see `echo/server/AGENTS.md`). ## Coordination keys (recap) The actors coordinate through Redis keys under the `coord:` prefix (`echo/server/dembrane/coordination.py`): `pending_chunks`, `processing_started`, `finalize_in_progress`, `finish_in_progress`, `chunk_decremented`. The agent service uses its own `agentic:run:*` lease/cancel keys (see [chat & the agent service](./chat-and-agent.md)). The full table is in [the processing pipeline](./processing-pipeline.md#coordination-idempotency-redis). > [!IMPORTANT] > The broker is Redis/Valkey. In production, watch for idle-timeout / eviction on the Valkey > cluster - an evicted broker loses queued messages, which is exactly what the catch-up jobs > exist to recover from. Treat broker memory and eviction policy as an operational concern. ## Adding a new job 1. Write the actor in `tasks.py` with an explicit `queue_name` (almost always `network`) and a sensible `priority`. Keep it idempotent - it may be retried or double-dispatched. 2. Use `run_async_in_new_loop` / `run_in_thread_pool` for any async or blocking work - never bare asyncio. 3. If it's periodic, add an `add_job` entry in `scheduler.py` referencing `dembrane.tasks:your_actor.send` with a `CronTrigger` and a stable `id`. 4. If it touches shared state across workers, add a Redis lock/counter in `coordination.py` and document it. --- *Related* - [The processing pipeline](./processing-pipeline.md) - [Chat & the agent service](./chat-and-agent.md) - [Architecture](./architecture.md) - [Local development](./local-development.md) --- # Local development dembrane is several services with shared infrastructure, so the recommended way to develop is the *devcontainer* plus `mprocs`: the container provides Postgres, Redis/Valkey and Directus; `mprocs` runs the host processes (API, workers, scheduler, the two frontends). This page gets you from a fresh checkout to a running stack. For what each service *is*, see [architecture](./architecture.md); for how it ships, see [deployment & releases](./deployment-and-releases.md). The operator-facing version of this - for people running dembrane outside our setup - is [self-hosting](../developer-external/self-hosting.md). ## What you'll be running | Process (`mprocs`) | Command | Port | |---|---|---| | `server` | `uv run uvicorn dembrane.main:app --port 8000 --reload --loop asyncio` | `:8000` | | `workers` | `uv run dramatiq-gevent --queues network --processes 1 --threads 10 dembrane.tasks` | - | | `workers-cpu` | `uv run dramatiq --queues cpu --processes 1 --threads 1 dembrane.tasks` | - | | `scheduler` | `uv run python -m dembrane.scheduler` | - | | `admin-dashboard` | `pnpm run dev` (in `frontend/`) | `:5173` | | `participant-portal` | `pnpm run participant:dev` (in `frontend/`) | `:5174` | Plus the infra from the devcontainer's compose file: *Postgres* (with pgvector), *Redis/Valkey*, *Directus* (`:8055`), and optionally the *agent service* (`:8001`). > [!NOTE] > `:5173` is the host *dashboard* and `:5174` is the participant *portal* - both are the > same `frontend/` codebase, served by two Vite dev servers so you can work on either in > isolation. See [architecture](./architecture.md#one-frontend-two-surfaces). ## The devcontainer Use the devcontainer for development - it configures and manages the services and their dependencies for you. Everything lives in `echo/.devcontainer/`: - `devcontainer.json` - the VS Code / Cursor "Dev Containers" definition. - `docker-compose.yml` - Postgres, Redis/Valkey, Directus, agent. - `docker-compose-s3.yml` - adds *MinIO* if you want local S3 instead of a cloud bucket. - `setup.sh` - provisioning (installs `pnpm` + `uv`, syncs deps). Prerequisites: VS Code or Cursor with the *Dev Containers* extension, Docker, and WSL on Windows. (The `echo/readme.md` is the canonical, screenshot-level walkthrough - follow it for the exact click-path; this page is the orientation.) The toolchain is `pnpm` for the frontend and `uv` for the Python server - local entry points always go through `uv run` so env and deps stay consistent. > [!TIP] > On this team's Macs the devcontainer runs on *Podman*, not Docker Desktop. If `docker` > commands behave oddly, check which engine your editor is wired to. ## Env files Two services each need their own env file, both copied from a checked-in sample: - `echo/server/.env` - from `echo/server/.env.sample`. The backend, workers and scheduler all read it. Config is parsed by `dembrane/settings.py` into `AppSettings` - add new vars as fields there and read them via `get_settings()`. *Never read `os.environ` directly.* - `echo/directus/.env` - from `echo/directus/.env.sample`. The Directus deployment's config (DB connection, admin creds, storage, its own email). Key things to set in `server/.env`: - *LLM model groups* - `LLM____*` for `MULTI_MODAL_PRO`, `MULTI_MODAL_FAST`, `TEXT_FAST`, with numbered fallbacks `LLM___1__*`. Full reference: `echo/docs/litellm_config.md` and [configuration & LLM providers](../developer-external/configuration-and-llm-providers.md). - *Transcription* - `TRANSCRIPTION_PROVIDER` (set to `Dembrane-26-07` for direct Vertex AI single-pass transcription, or `LiteLLM` for the fallback path) and the matching credentials/API config (such as `GCP_SA_JSON` for Vertex AI or `LITELLM_TRANSCRIPTION_*` for the fallback model). - *S3* - your bucket creds, or the MinIO endpoint if you're using `docker-compose-s3.yml`. - *Embeddings* - `EMBEDDING_*` (model, key, base URL, version) before anything calls `dembrane.embedding.embed_text`. - *Email* - `SENDGRID_API_KEY` for the app's transactional email (`email.py`, the HTTP API). Directus's own email is a *separate* SMTP path keyed by `EMAIL_SMTP_PASSWORD` - don't conflate them. > [!IMPORTANT] > There are *two independent email senders*: the Python app (SendGrid HTTP API, `email.py`) > and Directus itself (SendGrid SMTP). They use different keys and config. Setting one does not > affect the other. EU residency (`SENDGRID_REGION=eu`) must be set on both, with EU regional > subuser keys. See `echo/server/AGENTS.md`. ## S3: MinIO locally, or bring your own You have two options for object storage: - *MinIO* - bring up the stack with `docker-compose-s3.yml` to get a local S3-compatible bucket. Good for offline work; point the server's S3 env at it. - *Bring your own* - any S3-compatible endpoint (a dev DigitalOcean Space, AWS, etc.). For EU residency, use an EU endpoint. Audio chunks and generated files live here; the participant/iOS upload path writes to it via presigned URLs (see [the processing pipeline](./processing-pipeline.md)). ## Running a subset `mprocs` opens a TUI of all services (`j`/`k` select, `s` start, `x` stop, `r` restart, `a`/`X` stop-all, `q` quit). To launch just part of the stack: ```bash mprocs --names server,workers ``` Handy combos: - *API + workers only* (`server,workers,workers-cpu`) - backend work without the frontends. - *Just the dashboard* (`admin-dashboard`) against a remote backend - see `echo/docs/frontend_getting_started.md`. ## The agent service The standalone agent (`echo/agent/`) runs on `:8001`. It's its own `uv` project: ```bash cd echo/agent cp .env.sample .env # set GEMINI_API_KEY uv sync uv run uvicorn main:app --host 0.0.0.0 --port 8001 --reload ``` It comes up automatically in the devcontainer compose; run it by hand when you're iterating on the agent. See [chat & the agent service](./chat-and-agent.md). ## Checking your code Run `echo/check-code.sh` before pushing - it's the repo's lint/format/type gate. Tests live in `echo/server/tests/` and `echo/agent/tests/`. New work should land with tests, style and docs (see [contributing](../developer-external/contributing.md)). ## Common gotchas - *gevent + asyncio.* Inside Dramatiq actors, never run a bare asyncio loop - use `async_helpers`. See [background jobs](./background-jobs-and-scheduler.md). This bites people who write a new actor and call `asyncio.run(...)`. - *Directus schema drift.* If the dashboard 500s on data that "should" be there, your local Directus schema may be behind the snapshot. Push the snapshot (`echo/directus/sync/`) - and mind the `is_indexed` / drop-index ordering pitfall when syncing. - *Misfired scheduler jobs.* The scheduler sets `misfire_grace_time=60` and `coalesce=True` so jobs run late rather than never on a loaded host - if a cron "didn't fire", check the worker logs, not just the scheduler. --- *Related* - [Architecture](./architecture.md) - [Background jobs & scheduler](./background-jobs-and-scheduler.md) - [Deployment & releases](./deployment-and-releases.md) - [Self-hosting (external)](../developer-external/self-hosting.md) - [Configuration & LLM providers (external)](../developer-external/configuration-and-llm-providers.md) --- # Deployment & releases dembrane has a short, opinionated path from a merged PR to production. `main` continuously deploys to a staging environment; production ships from *release tags* roughly every two weeks. This page covers the branches, the environments, the GitOps repo, the Docker images, and the migration ritual. The canonical engineering docs are `echo/docs/branching_and_releases.md` and `echo/docs/database_migrations.md` - this page is the orientation and the gotchas. ## The environments | Environment | URL | Deploys from | Notes | |---|---|---|---| | *Testing* | `dashboard.testing.dembrane.com` | `testing` branch (on push) | Shared, unprotected staging. | | *Echo Next* | `dashboard.echo-next.dembrane.com` | `main` (on merge) | Staging / preview; auto-deploys ~2 min after merge. | | *Production* | `dashboard.dembrane.com` | GitHub *release tag* on `main` | Every ~2 weeks. | Each environment has matching `dashboard.*`, `portal.*` and `directus.*` subdomains. > [!NOTE] > "Echo Next" is the staging name (`dashboard.echo-next.dembrane.com`). It is not a separate > product - it's `main` running ahead of the production tag. Use it to confirm a merged change > behaves before it's cut into a release. ## The development flow ``` main ──────────●──────────────●──── (auto-deploys to Echo Next) \ ↗ PR | feat/ECHO-123 | \ | testing ────→ dashboard.testing.dembrane.com ``` 1. *Branch off `main` - `feat/ECHO-xxx-description` or similar. 2. *Develop* on the feature branch. 3. *(Optional) test on the testing environment* - merge your branch into `testing` to deploy to `dashboard.testing.dembrane.com`. 4. *Open a PR* to `main`. 5. *After merge* - changes auto-deploy to Echo Next (~2 min). 6. *After you're done testing* - reset `testing` back to `main`. ### The testing-branch reset rule `testing` is *shared and unprotected* - anyone can push to it. So before you use it, check nobody else is mid-flight, and when you're done, reset it: ```bash # before: is testing ahead of main? (someone else's work?) git log main..testing --oneline # after: hand it back clean git checkout testing git reset --hard origin/main git push --force ``` > [!WARNING] > Don't force-push `testing` over someone else's in-flight changes. Run the `git log > main..testing` check first; if there are commits ahead of `main`, ask the team before > overwriting. `testing` is a scratch environment, not a branch to build on. ## The release process Releases align with the two-week Linear cycles: 1. *Accumulate* changes on `main` through the cycle. 2. *Pre-release checks* (the easy-to-forget ones): - *New env vars* - anything added as a field on `AppSettings` in `settings.py`, or exported from the frontend `config.ts`. If a release needs a new var, it must be set in the GitOps repo *before* the tag, or the new pods crash-loop. *Check the env-flag/feature-flag state too* - make sure a half-built feature isn't about to light up in prod. - *Directus migrations* - run any data/schema migrations (see below). - *GitOps env* - update deployment env vars in the GitOps repo if needed. 3. *Tag and release* - cut a GitHub release from a commit on `main`. 4. The release *auto-deploys to production*: - *Backend* - new image tags are picked up by the GitOps repo (`dembrane/echo-gitops`); *Argo CD* auto-syncs them. - *Frontend* - auto-deploys via Vercel. ### Hotfixes When a critical prod bug needs fixing but `main` has unreleased changes that *shouldn't* go out, branch the fix off the released tag, not off `main`, and release it on its own. The exact cherry-pick recipe is in `echo/docs/branching_and_releases.md` - follow it rather than improvising. ## The GitOps repo Production infra lives in a separate repo, `dembrane/echo-gitops`: - *Terraform* - DigitalOcean infrastructure (clusters, managed Postgres, Spaces, Valkey). - *Helm* - the chart that templates the Kubernetes resources for each service. - *Argo CD* - continuous delivery; it watches the repo and auto-syncs the cluster to match. New image tags from a release are reconciled by Argo, not pushed by hand. So a backend release is really: build image → bump tag in `echo-gitops` → Argo syncs. Changing a prod env var means editing the GitOps repo (often a sealed/encrypted value), not the cluster directly. ## The Docker images Four service images are built from the monorepo: | Image | Dockerfile | Notes | |---|---|---| | *server* | `echo/server/Dockerfile` | The FastAPI API, workers and scheduler share this image; the entrypoint (`prod.sh` / `prod-worker.sh` / `prod-worker-cpu.sh` / `prod-scheduler.sh`) selects the role. The API runs under the custom asyncio uvicorn worker. | | *agent* | `echo/agent/Dockerfile` | The standalone agent service (`:8001`). Separate dep stack from the server (that's why it's its own service). | | *directus* | `echo/directus/Dockerfile` | The Directus deployment plus the `directus-sync` tooling. | | *usage-tracker* | `echo/tools/usage-tracker/Dockerfile` | Operational usage tooling. | The frontend isn't a container in this flow - it deploys via Vercel. > [!IMPORTANT] > The agent has historically been easy to miss in the prod build matrix (it was once only built > by the testing pipeline, causing an `ImagePullBackOff` in prod). When you change CI image > builds, confirm *agent* is in the production matrix, not just testing. ## Database migrations Schema lives in Directus and is managed with `directus-sync`. The ritual (`echo/docs/database_migrations.md`): 1. `cd echo/directus` 2. Run `./sync.sh` and choose *push* (option 1) to apply the schema snapshot. 3. Run any required raw SQL on the database (`psql -h postgres -p 5432 -U dembrane`; default dev password `dembrane`), e.g. `CREATE EXTENSION vector;` for pgvector. Some changes are *two-step and order-sensitive* - deploy the code first, then run the SQL. The membership unique indexes (one active membership per user per org/workspace), which the invite-race fix in `api/v2/_invite_helpers.py` depends on, are the canonical example: deploy the API change, *then* create the partial unique indexes. If index creation fails on a duplicate key, dedupe the active rows first, then re-run. > [!WARNING] > Pushing schema to prod has a known pitfall: a `directus-sync` push can 500 with "drop index > does not exist" if the snapshot disagrees with reality (the `is_indexed` pitfall). Reconcile > the snapshot before pushing, and test the push against staging first. When in doubt, follow > `echo/docs/database_migrations.md` exactly rather than improvising the SQL. ## Where the rules live - `echo/docs/branching_and_releases.md` - the authoritative branch/release/hotfix process. - `echo/docs/database_migrations.md` - the migration ritual and the index recipes. - `echo/docs/adr/` - the ADRs (0001–0005) that explain why the data and billing model look the way they do; relevant when a release touches roles, seats, tiers or invites. See [roles & policies in code](./roles-and-policies.md). --- *Related* - [Architecture](./architecture.md) - [Local development](./local-development.md) - [The data model](./data-model.md) - [Background jobs & scheduler](./background-jobs-and-scheduler.md) - [Self-hosting (external)](../developer-external/self-hosting.md) --- # Developing & maintaining the docs Good docs are how this codebase stays maintainable: they are what hosts read, what the in-app assistant cites in chat, and what agents use to reason about the system. A stale page misleads all three. So docs and code are kept in sync *as a process*, not by memory. The model is a two-way sync: - *Code → docs* (live today): a merged code change gets propagated into every affected page, as a reviewable PR. - *Docs → code* (planned): editing a doc trickles the change down to the code it describes, using the code references on each page - also as a reviewable PR. Either direction, the change is *subject to review*. Nothing lands on the site without a human confirming the docs now say what the code does. Over time this pushes both sides to improve: docs that must match code stay honest, and code that must be documentable stays explainable and testable. ## Where things live | Piece | Path | |---|---| | The published corpus | `docs/` (repo root), deployed to docs.dembrane.com on every main push touching `docs/**` | | What is true | `docs/_authoring/FACTS.md` - the accuracy anchor every page must agree with | | How to write it | `docs/_authoring/STYLE.md` - voice, language, links, structure | | The code → docs process | `.claude/skills/code-to-docs/SKILL.md` - the operational skill an agent (or you) runs | | Engineering notes (not the site) | `echo/docs/` - ADRs, plans, backlogs | ## The code → docs process The full procedure is the `code-to-docs` skill; ask an agent to "run code-to-docs on PR #N" or follow it by hand. The shape: 1. *Classify the diff.* Only user-observable changes need user docs: UI, routes, permissions, tiers, endpoints, behaviour. "No docs impact" is a valid conclusion - state it. Internal architecture changes may still touch these developer pages. 2. *Map diff → pages, three ways.* By feature (`docs/features/` owns each capability), by audience (every `docs/users//` retelling), and by reference (grep the docs for exact strings the diff touched - old labels are the highest-value hits). Union the three lists, then always check `FACTS.md`. 3. *Update facts first.* `FACTS.md`, then the feature page, then the audience pages, then trickle to pages that link to or restate what you changed. 4. *Ground every claim in code.* Read the code, not the PR description. Copy UI labels exactly from source. If you can't verify it, leave it out - an invented detail becomes a confidently wrong assistant answer. 5. *Verify and open a PR.* Links resolve, new pages are reachable from `map.md`, the site builds. The PR body maps each docs hunk to the code change that caused it, and lists pages checked but deliberately left alone. ## When to run it - After merging any PR that changes user-visible behaviour - ideally the same day. - On a cadence, as a catch-up: diff everything merged since the docs were last synced (`git log --since= -- ':!docs'`) and run the process over the batch. - Whenever someone reports a stale page: fix the page *and* the missed diff that made it stale. ## The docs → code direction (planned) The other half: a docs edit becomes the spec, and the change trickles down to the code the page references, plus every related item, as a reviewable PR. That needs stable code references on each page before it can be trusted; the direction is recorded here so the process has a home when it lands. ## Related - [Internal developer overview](./index.md) - orientation for engineers. - [Deployment & releases](./deployment-and-releases.md) - how a docs merge reaches the site (main push → Pages deploy). - [Chat & the agent service](./chat-and-agent.md) - the assistant that cites these pages in chat. --- # Guides by who you are dembrane looks different depending on why you're here. These guides take the [features](../features/index.md) and retell them from your point of view: when you'd reach for each one, and what you can do in your role. ## The people of dembrane - *[Host](./host/index.md)* - you run sessions and make sense of them. You create projects, collect conversations, read transcripts, chat with your data, and build reports. Most dashboard users are hosts. - *[Host - partner](./host-partner/index.md)* - you're a host inside a *partner* organisation that runs dembrane on behalf of external clients. You get external-client workspaces, the free observer role, and rules for data ownership and handoff. - *[Staff](./staff/index.md)* - you work at dembrane. You look after billing, account health, upgrade requests, partner operations, and trainings, through the admin panel. - *[Participant](./participant/index.md)* - someone invited you to record. No account, no setup: scan a code or open a link, talk, done. These pages explain what to expect and what happens to your words. - *[Developer - external](./developer-external/index.md)* - you self-host dembrane, integrate with its API, or contribute to the open-source project. - *[Developer - internal](./developer-internal/index.md)* - you work on the dembrane codebase. Architecture, the data model, the processing pipeline, and how it all ships. > [!TIP] > Roles can overlap. A host is often also a workspace admin; a partner is a host with extra > abilities; a staff member might also host their own projects. Read whichever guides fit > what you're doing today. --- # Organisations & workspaces dembrane has two levels above your actual work. An *organisation* is your company or institution; inside it live *workspaces*, and inside each workspace live the [projects](./projects.md) where conversations, transcripts, chat, and reports sit. - The *organisation* holds your members, your workspaces, and your pooled billing. Org admins create workspaces and see across all of them; the org owner has full control and can't be demoted through the interface. - A *workspace* is one programme of work with a clear boundary - its own members and [roles](./roles-and-permissions.md#workspace-roles), its own projects, its own [settings](./visibility-and-discovery.md), and its own [tier](./tiers-and-billing.md). A research study, a client engagement, a department's town halls. To create a workspace you need to be an org *admin* or *owner*. To manage one, you need to be its owner or admin. See [roles & permissions](./roles-and-permissions.md). ## New workspace, or new project? This is the question that comes up most. The short version: a workspace is the unit of *billing and access*; a [project](./projects.md) is the unit of *work*. When in doubt, prefer a project - workspaces are heavier, each with its own members and tier. | Your situation | Make a… | |---|---| | A new study or consultation within the same team | *project* in an existing workspace | | A new client or external engagement (especially as a [partner](./partner-program.md)) | *workspace* | | A sensitive programme that should be [private](./visibility-and-discovery.md) from the rest of the org | *workspace* | | A separate team that shouldn't share members or settings | *workspace* | | A programme that needs audit logs or a higher [tier](./tiers-and-billing.md) than the rest | *workspace* | Projects can be *moved* between workspaces later if work changes hands - see [data ownership & compliance](./data-ownership-and-compliance.md). ## Membership at the two levels is separate Being in an organisation doesn't put you in any of its workspaces, and being in a workspace doesn't put you in the org. So: - You can belong to an org with *no workspaces yet*. - You can be inside a workspace *without belonging to the org at all* - that's exactly what the [external](./roles-and-permissions.md#external-is-a-role-not-a-flag) and [observer](./roles-and-permissions.md#the-free-read-only-observer) roles are: outside collaborators who work in a workspace while staying outside your organisation. Bringing an outside collaborator *into* the organisation as a full member is therefore a deliberate step, not a toggle - the path is in [external is a role](./roles-and-permissions.md#external-is-a-role-not-a-flag). ## How billing flows Billing attaches to a *billing account*: - *Internal workspaces* share one pooled account across the organisation, and [seats](./tiers-and-billing.md#seats) pool across them. - *External-client workspaces*, where a [partner](./partner-program.md) hosts work for someone else, get their own separate account. So internal costs roll up into the org, while an external-client workspace stands on its own. The full picture is in [tiers & billing](./tiers-and-billing.md#how-billing-is-organised) and [data ownership & compliance](./data-ownership-and-compliance.md). ## Getting started A new organisation begins with an onboarding wizard that creates your first workspace and project together, so you're recording within minutes. From there you add people via [invites](./invites-and-access.md), set [visibility](./visibility-and-discovery.md), and choose a [tier](./tiers-and-billing.md). Hosts can follow the [host getting-started guide](../users/host/getting-started.md). ## Related - [Projects](./projects.md) - what lives inside a workspace. - [Roles & permissions](./roles-and-permissions.md) - who can do what at each level. - [Tiers & billing](./tiers-and-billing.md) - how billing accounts and seats work. - [Visibility & discovery](./visibility-and-discovery.md) - who can find and join a workspace. - [Invites & access](./invites-and-access.md) - adding people to an org or workspace. - [The partner program](./partner-program.md) - external-client workspaces and their separate billing. --- # Invites & access To add someone, open the invite modal, pick their [role](./roles-and-permissions.md), and either enter their email or generate a link. dembrane works out the rest - whether they already have an account, whether they're already a member, and whether they need an email. You need *member management* rights to do this: workspace *owner* or *admin* to invite into a workspace, org *owner* or *admin* to invite into an organisation. Plain members and the lighter roles can't invite. ## Add someone 1. Open the invite modal in the workspace (or organisation) you want them in. 2. Pick a [role](./roles-and-permissions.md). Which roles you can offer depends on where you are: - *Workspace* - admin, member, billing, external, or observer. - *Organisation* - member, admin, billing, or owner. There's no external at the org level - external only exists inside a workspace. 3. Invite *by email* (dembrane sends a secure link that expires after 7 days) or *by link* (you generate it and share it however you like - handy when you don't have someone's exact email, or you're inviting a group). Either way, the role you chose is baked in. ## What happens next You don't manage these outcomes - dembrane picks the right one and you'll see it in the member list: - *Already a member* - nothing to do, they're in. - *Reactivated* - they were a member before and are restored. - *Added* - they already have a dembrane account, so they're in straight away. - *Invited* - they're new, so a pending invite is created and the link is emailed (valid 7 days). When the recipient opens their link they land on the accept page. If they're logged out, they sign in or register first and the invite then applies. If they're signed in as a different account than the invite was for, dembrane tells them so they can switch. > [!TIP] > People don't need an account before you invite them. If they're new, accepting walks them > through registration, then drops them into the workspace with the role you chose. ## You can't grant above your own role The workspace hierarchy is *observer < external < member < billing < admin < owner*. You can never grant a role higher than your own - an admin can invite admins, members, billing, externals, and observers, but not an owner. Only an owner can grant owner. This stops anyone escalating access beyond what they hold. (Full hierarchy in [roles & permissions](./roles-and-permissions.md#workspace-roles).) ## Pending invites and access requests Two lists keep things tidy: - *Pending invites* - people you've invited who haven't accepted. Re-send or cancel as needed; email invites expire after 7 days. - *Access requests* - people asking to join on their own, rather than being invited. Anyone who can *discover* a workspace - an org admin browsing [discoverable workspaces](./visibility-and-discovery.md), or a member who found an open one - can request access, and a workspace admin approves or denies it. For organisations, admins get a single matrix bringing members, workspaces, access requests, and pending invites together - see [organisations & workspaces](./organisations-and-workspaces.md). ## How invites affect seats Inviting touches [seats](./tiers-and-billing.md#seats), but gently: - *Never blocked.* You can always send an invite - dembrane counts the seat and bills it rather than walling you off because you're "out of seats." - *Pending invites count.* A billable seat is reserved the moment you invite someone, not just when they accept. - *Observer invites are free.* Because [observer](./roles-and-permissions.md#the-free-read-only-observer) is free, inviting one doesn't add to your seat count. So invite freely and watch the count. If someone only needs to *see* results, an observer costs nothing. > [!NOTE] > When a [partner](./partner-program.md) creates an external-client workspace, dembrane > auto-invites the named data owner as a free observer - they can always watch their own data > being handled, at no cost. See [data ownership & compliance](./data-ownership-and-compliance.md). ## Related - [Roles & permissions](./roles-and-permissions.md) - the roles you grant, and the hierarchy that limits you. - [Visibility & discovery](./visibility-and-discovery.md) - what lets people find and request a workspace in the first place. - [Tiers & billing](./tiers-and-billing.md) - how seats are counted as you add people. - [Organisations & workspaces](./organisations-and-workspaces.md) - the org vs workspace distinction that decides which roles are available. --- # Visibility & discovery *Visibility* decides who can see and find a [workspace](./organisations-and-workspaces.md) before anyone is given a [role](./roles-and-permissions.md) in it. There are three settings. Pick by how much you want the rest of your organisation to discover. | You want… | Use | Who can find it | |---|---|---| | Everyone in the org to find and use it | *Open to the organisation* (default) | All org members; admins auto-join | | Org admins to discover it, others by invite only | *Invite-only* *(needs Innovator+)* | Org admins; everyone else needs an [invite](./invites-and-access.md) | | Only invited people; not discoverable | *Private* *(needs Innovator+)* | Invited people only | To change a workspace's visibility you need to manage its settings - workspace *owner* or *admin* (see [roles & permissions](./roles-and-permissions.md)). ## What each one means - *Open to the organisation* is the default and the low-friction choice. Every org member sees the workspace and org admins auto-join. Good for shared internal work with nothing to hide. It's free at every [tier](./tiers-and-billing.md), including Free. - *Invite-only* is the middle ground. Org admins can still discover it and join themselves, but everyone else needs an [invite](./invites-and-access.md) or an approved access request. - *Private* is the tightest. Only invited people, and org admins do *not* auto-join - discovery stops at the door. The one exception is the org *owner*, who can still carve in (see [organisations & workspaces](./organisations-and-workspaces.md)). Use it for confidential programmes or client work that shouldn't appear in colleagues' lists. > [!TIP] > If you specifically don't want org admins wandering in, choose *private*. Invite-only still > lets them discover and self-join; private does not. Visibility and roles do different jobs. Visibility decides who can *find* a workspace and ask to join; the [role](./roles-and-permissions.md) you're then granted decides what you can *do*. A workspace can be wide open to discovery and still only let people read. ## The one paywalled transition Moving a workspace *out of* "open to the organisation" - to invite-only or private - needs *Innovator or above*. Every other visibility change is free. The reasoning: being open is the free default. Tightening a workspace down so the rest of the org can't see it is the paid capability. So on Free, workspaces stay open; to lock one down you'll be on [Innovator, Changemaker, or Guardian](./tiers-and-billing.md). If you're a [member](./roles-and-permissions.md#what-member-really-means-day-to-day) without billing rights, you'd [request an upgrade](./tiers-and-billing.md#requesting-an-upgrade). ## How org admins discover and self-join Org admins get a *discoverable workspaces* view listing the workspaces they can reach - alongside [access requests and pending invites](./invites-and-access.md). It's how an admin steps into a workspace without waiting for an invite, where visibility allows: - *Open* workspaces appear to all org members; admins are auto-joined. - *Invite-only* workspaces are discoverable to admins, who can self-join. - *Private* workspaces are invisible to discovery (except to the org owner). ## Related - [Roles & permissions](./roles-and-permissions.md) - what people can do once they're in. - [Tiers & billing](./tiers-and-billing.md) - why tightening visibility needs Innovator+. - [Organisations & workspaces](./organisations-and-workspaces.md) - the structure visibility operates on, and the org owner's special access. - [Invites & access](./invites-and-access.md) - how people actually join once they've found a workspace. --- # Projects A project holds one body of work: the conversations that belong together, plus everything that grows out of them - transcripts, summaries, themes, chats and reports. You record into a project and analyse its conversations as a set. A good rule: one *question* or *engagement* per project. If you'd report on it as one thing, it's one project. Projects live inside a [workspace](./organisations-and-workspaces.md), so what you can do depends on your [workspace role](./roles-and-permissions.md). Members and up can create and edit; only owners and admins can delete, move, or make a project private. Creating a *private* project needs an *Innovator* workspace or above (see [tiers & billing](./tiers-and-billing.md)); everything else works on every tier. ## Creating a project Open your workspace, go to *Projects*, choose *New project*, and fill in three short steps: 1. *Name & context.* The *name* is dashboard-only - participants never see it, and you can change it later. *Context* is the one that matters: describe the project as you would to a sincerely interested, curious friend - the goal, who's in the room, what you want to learn, anything unique about it. Include place names, locations and common abbreviations. The language model reads this when it writes summaries and answers, so honest context means sharper analysis. 2. *Access.* Choose who in your workspace can see and work on the project. This sets its [visibility](#visibility). *Private* needs Innovator or above. 3. *Review.* A final check, then create. You land on the project home, ready to set up [the portal](./portal-editor.md) and start [recording](./recording.md). > [!TIP] > Don't agonise over context up front. Re-running a summary after you've sharpened it is > cheap, and dembrane uses the newer context next time. ## Project settings Open a project and go to *Settings*. - *Name* - rename at any time. - *Conversation language* - the project default. Set it to what participants will actually speak: if a Dutch conversation is set to English, it gets transcribed as English. (Transcription is multilingual regardless - see [transcription](./transcription.md).) - *Visibility* - open, invite-only, or private (see [below](#visibility)). - *Conversation toggle* - switch off the ability to start *new* conversations when an engagement closes. Existing conversations stay readable. - *Participant-name collection* - whether the portal asks people for a name. Finer control lives in the [portal editor](./portal-editor.md). - *Move project* - move it into another workspace (owners and admins). Handy for handing work between teams, or for partners moving between an internal and an external-client workspace. - *Delete project* - permanent, and takes the conversations, transcripts and reports with it. > [!WARNING] > Deleting can't be undone. If you only want to stop new recordings, switch off the > conversation toggle instead. The *portal editor*, *access* and *usage* sections each have their own home: shaping the recording experience lives in [the portal editor](./portal-editor.md), and metered hours are explained in [tiers & billing](./tiers-and-billing.md). ## Visibility A project sits in one of three states, mirroring how [workspaces handle visibility](./visibility-and-discovery.md): - *Open* - everyone in the workspace can see and (per their role) work on it. The simplest default for a team that trusts each other. - *Invite-only* - visible to people who've been added, plus workspace admins. - *Private* - visible only to people you give access, person by person, from *Settings → Access*. Admins aren't auto-joined. Adding a colleague to a private project doesn't change their workspace role; it just opens that one project to them. Needs Innovator or above. ## Finding projects again The *Projects* view has three ways back: *Home* (your projects, most relevant first), *Pinned* (keep what you're working on at the top), and *Search* (find one by name when the list grows). ## Related - [Organisations & workspaces](./organisations-and-workspaces.md) - the container a project lives in. - [The portal editor](./portal-editor.md) - shape how people record for this project. - [Conversations & transcripts](./conversations-and-transcripts.md) - what fills a project up. - [Roles & permissions](./roles-and-permissions.md) and [tiers & billing](./tiers-and-billing.md) - who can do what, and what each plan unlocks. --- # Recording Recording is how spoken words get into dembrane. Someone talks; dembrane captures the audio, uploads it safely in the background, and hands it to [transcription](./transcription.md). It's built for real rooms - patchy wifi, a phone that locks itself, a backgrounded tab - without losing what people said. Recording counts towards your workspace's metered hours. The *Free* tier includes *1 hour*; every paid tier is unlimited (see [tiers & billing](./tiers-and-billing.md)). ## Two ways to collect Most recording is done by participants, with no account and nothing to install: - *A QR code* - generated for you in the [portal editor](./portal-editor.md). Print it, project it, or stick it on a table; a phone camera opens the portal. - *A direct link* - copy and share the portal link by email, on a slide, or in a chat. Both open [the participant portal](./portal-and-participant-experience.md), which walks people through onboarding, consent, a mic check, and recording. You can also record yourself. From the dashboard you get the same recorder participants use, with the same pause, resume and stop controls - useful when you're the one in the room. [dembrane Go](./mobile-app-dembrane-go.md), the native iOS app (currently in beta), is the most robust option when connectivity is shaky: it records to the device first and uploads when it can, so a dead spot never costs you the conversation. ## The mic check Before recording, the portal offers a *mic check* so a participant can confirm the right microphone is picked up and the level looks healthy - the quickest way to avoid recording five minutes of silence. During recording, a live level meter (waveform) shows that audio is actually coming through. ## When the transcript appears The conversation shows up in your dashboard as soon as it starts. The transcript appears about *30 seconds to a minute after the start*. The wait is normal: audio is sent in 30-second pieces, and the higher-quality transcription takes a little extra processing time. After that it keeps growing as people speak. ## Watch it live: the Monitor *[dembrane next only](./dembrane-next.md).* While people record, the project's *Monitor* page (in the project sidebar) shows the whole room in real time: - *Live participant flow* - from the moment someone scans the QR, they appear and move across three stages: *Scanned → Setting up → Recording*. You see people stall at the mic check or drop off before recording, while it's still fixable. - *Each live recording* - who's recording, paused, or finishing, with a live transcript snippet and a running duration. - *Is the audio coming in?* - each live recording shows a small level meter, so you can see audio is actually flowing; when it goes silent it nudges you to *check the mic isn't muted*. A recording that was sending audio and then stopped gets an *Audio stopped?* warning (they may have lost connection); a locked phone or hidden tab shows *Screen locked*, because recording pauses until they come back. - *Transcription progress* - a *Transcribing* count per conversation, a rough *catch up* estimate when a backlog builds, and an *Error* badge when something needs attention. The project home page shows the same view in brief as *Live & recent*. See [the live monitor](./live-monitor.md) feature guide for a complete breakdown of stages and indicators, and [collecting conversations](../users/host/collecting-conversations.md#watch-the-room-the-monitor-page) for how to use it mid-session. ## Pause, resume, stop - *Pause / resume* - step away mid-session without ending the recording. What's recorded so far is safe; resuming continues the same conversation. - *Stop* - end the recording. The final pieces finish uploading and [transcription](./transcription.md) and summarising take over. Audio is uploaded in small pieces as it's spoken rather than as one big file at the end, so an interruption only ever costs the current piece - and a weak connection retries one small piece instead of resending everything. A participant's name and email are collected *only if you asked for them* in the [portal editor](./portal-editor.md), and transcripts can be [anonymised](./transcription.md). How dembrane keeps it is covered in [data ownership & compliance](./data-ownership-and-compliance.md). > [!TIP] > If a venue's wifi is shaky, dembrane Go is safer than a browser - it records locally and > uploads opportunistically. ## Related - [Transcription](./transcription.md) - what happens to the audio once it's uploaded. - [The participant portal](./portal-and-participant-experience.md) - the no-account recording experience, end to end. - [dembrane Go (mobile)](./mobile-app-dembrane-go.md) - the native iOS recorder (beta). - [Tiers & billing](./tiers-and-billing.md) - recording hours and what's metered. --- # The live monitor When you run a session (a workshop, a consultation, a set of interviews), people scan a QR code and record on their own phones, all at the same time. You cannot stand behind each of them. The live monitor is the room you watch instead: it shows every participant as they arrive, set up, and record, so you can see who is going well, who is stuck, and who needs a hand, without interrupting anyone. There is really one person in this story: the *host* (a project admin or facilitator) watching a session happen. Everything below is what you, the host, see and can do on the Monitor page. The participants just record as usual on their phones; the monitor is your window onto that. ## Where to find it Open your project and go to *Monitor*. The page also shows the project's QR code, so you can put it on a screen for people to scan and join. The page is live. It updates on its own as people scan, record, pause, and finish. You never refresh. If the live connection drops for a moment it keeps working on a slower update and shows a small *Reconnecting* note until it comes back. ## The live participant flow At the top is the flow: people moving left to right through three stages. - *Scanned*: they opened the portal from the QR code. - *Setting up*: they are moving through consent, the mic check, and entering their details. - *Recording*: they have started a conversation and audio is being captured. Each dot is a person. It is a live picture of where everyone is right now, so you can see, for example, that ten people scanned but only three have started recording, and go help the seven who are stuck in setup. Click any dot to see more. A person still in setup shows a *visitor* card: what they have done so far (scanned, accepted terms, mic checked or skipped or blocked, entered details), each with a time, plus their device and any weak network or low battery warning. A person who is recording opens the conversation view described further down. ## The conversation list Below the flow is the list of conversations, grouped by tag so a busy project stays scannable. Within a group the rows keep a steady order (by when each person started), so they do not jump around while you read them. Each row is one participant, and it is built to answer a host's questions at a glance. ### What state they are in A colored pill tells you what the person is doing right now: *Recording*, *Paused*, *Verifying*, *Exploring*, *Typing*, *Finishing*, *Finished*, *Waiting*, *Just started*, *Away* (their screen is locked or the tab is hidden), *Left* (they closed the tab), or *Offline* (we have lost contact). The recording pill gently pulses so an active recording is easy to spot. ### How long they have recorded A small clock shows the recorded length, with a state-colored dot beside it. It counts up while they record, holds still while they are paused, and settles on the final length when they finish. It only ever shows real recording time, so a paused or not-yet-started session never drifts upward. ### Whether audio is really coming in While someone is recording, a small microphone meter shows how loud their mic is. Lit bars mean audio is flowing; empty bars mean it is very quiet, which is your cue to check they are not muted. It reflects the loudest moment over the last few seconds, so a natural pause between sentences does not read as silence. ### What they are saying The most recent line of their transcript fades in under the pill, so you can follow the gist without opening anything. If a conversation is anonymized, personal details in that line are shown as redaction badges rather than the original words. On some plans, transcripts for new conversations are locked; the row shows a prompt to upgrade instead of the text. ### When something needs attention Warnings surface right on the row so you can act: - *Audio stopped?*: they were recording but nothing has arrived for a while. They may have lost connection or locked their phone. - *Screen locked*: their screen is locked or the tab is hidden, so recording is paused until they come back. This is gentle, not an alarm. - A weak-network or low-battery icon when their device reports one. - *Error*: some recent audio could not be transcribed. The recording itself is still saved. ### How transcription is going A badge shows transcription progress: *Transcribing N clips* while it catches up, or *Transcribed* once a conversation's audio is done. A language tag shows the detected or chosen language. ## The summary line Across the top of the list is a running count so you can gauge the whole session without reading every row: how many are *live*, how many are *offline*, how many have *audio stopped*, how many are *transcribing*, how many have *errors*, and a rough *catch up ~N min* estimate for how long the transcription backlog will take to clear. The estimate is deliberately conservative, so it never over-promises. ## Opening a conversation Click a row (or its pencil) to open the conversation. From here you can: - *Rename* the participant, so an anonymous row becomes a name you recognize. - *Edit tags*, to group or re-group the conversation on the fly. - See the *timeline*: their journey (scanned the QR, accepted terms, mic checked, entered details), then when they joined the conversation, started recording, and were last heard. - *Delete* the conversation, with a confirmation first. Deleted conversations disappear from the monitor and the flow right away. - *Open conversation* to jump to the full conversation view. ## Privacy and what stays hidden - Anonymized conversations have personal details redacted in the live transcript line, shown as badges instead of the words. - On plans where transcripts are gated, the monitor shows the state and progress of a conversation but not its transcript text, with a prompt to upgrade. - Deleted conversations are never shown here. ## At a glance | | What it tells you | |---|---| | Participant flow | Where everyone is: scanned, setting up, or recording | | State pill | What each person is doing right now | | Recording clock | Real recorded length, paused-aware | | Mic meter | Whether audio is actually coming in | | Transcript line | The latest words, redacted where anonymized | | Warnings | Audio stopped, screen locked, weak network, low battery, errors | | Transcription badge | How far along transcription is, and a backlog estimate | | Conversation view | Rename, edit tags, timeline, delete, open | | Updates | Live, on their own, with automatic reconnect | --- # The participant portal The portal is what a participant goes through to record for one of your projects. They open a link or scan a QR code, and the portal walks them from a welcome screen, through consent and a mic check, into recording, and out the other side. There's *no account* and nothing to install - it runs in a phone or laptop browser. As a host you don't record through the portal so much as *shape* it; everything below is configured in [the portal editor](./portal-editor.md). You get a participant in two ways, both pointing at the same place: a *link* you share, or a *QR code* you print or project. The portal is per language - share a link in the participant's language and the whole flow appears in the right one. ## What a participant does 1. *Start.* A few onboarding cards - welcome, instructions, and the consent and legal text (with a link to the privacy statement), all written by you. If you've asked for it, this is where they fill in a name and/or email. Then a language choice, if you offer more than one. 2. *Mic check.* A quick check that the right microphone is picked up and the level is healthy, so nobody records five minutes of silence. 3. *Record.* They record their contribution, with a live level meter and *pause / resume / stop*. Audio uploads in small pieces as they speak (see [recording](./recording.md)). 4. *Type instead.* Anyone who'd rather not speak can write their contribution as text and have it treated the same way. 5. *Refine.* After recording they can review their segments and choose which to keep, so a fumbled start doesn't have to make the transcript. 6. *Verify.* If you've enabled it, they're shown what dembrane drew from their conversation and can *approve, reject or modify* it - keeping the participant, not the model, in charge of how they're represented. 7. *Finish.* A closing message you wrote, and - depending on your settings - the offer of a report and a chance to subscribe to updates. 8. *Report.* An optional summary of their own contribution. See [your report](../users/participant/your-report.md) for the participant's view. The portal asks for nothing a participant doesn't have to give: no sign-up, no password, a name or email only if you switched it on, and consent taken explicitly before anyone records. Transcripts can be [anonymised](./transcription.md); how the data is handled is in [data ownership & compliance](./data-ownership-and-compliance.md). ## Ready Check Go (tell participants before they record) A handful of things make the difference between a clean recording and a lost one: - *Be on good wifi or 5G.* - *Allow microphone access* when prompted. - *Keep the screen on.* A black screen means no recording. A well-charged phone is less likely to sleep. - *Turn on Do Not Disturb* - better privacy, fewer interruptions. > [!TIP] > Test your own portal before an event. Open the QR or link on your phone and run through it > once - it's the quickest way to catch a confusing instruction or a missing consent line while > you can still fix it in [the portal editor](./portal-editor.md). ## Related - [The portal editor](./portal-editor.md) - where you configure everything above. - [Recording](./recording.md) - the capture mechanics behind step 3. - [Transcription](./transcription.md) - what happens to the audio afterwards. - Participant guides: [what to expect](../users/participant/what-to-expect.md), [recording your conversation](../users/participant/recording-your-conversation.md), [refining & verifying](../users/participant/refining-and-verifying.md), [your privacy & your data](../users/participant/your-privacy-and-data.md). --- # The portal editor The portal editor is where you shape what a participant sees and does when they record for a project. Every screen of [the participant portal](./portal-and-participant-experience.md) - the welcome cards, the consent text, the languages, what's asked of people, what they see at the end - is set here. Configure it once per project, preview it live, then share the QR code or link. It lives at a project's *Settings → portal editor*. Editing needs a role that can edit projects - *owner*, *admin* or *member* (and *external* collaborators on projects shared with them); see [roles & permissions](./roles-and-permissions.md). Available on every [tier](./tiers-and-billing.md). ## The experience - *Tutorial* - which onboarding set the welcome cards show. - *Language* - the portal's default language. You can also share per-language links. Note: this only changes the *intro screens* - the welcome, instructions and consent. Transcripts stay in the language people actually speak (see [transcription](./transcription.md)). - *Default conversation title* - the title new conversations get. - *Default description* - the intro text participants see. - *Finish text* - the closing message on the completion screen. ## Transcript quality and privacy - *Key terms* - the proper nouns, names and jargon you want transcription to get right. These are fed into the cleanup pass so a transcript spells "Janssen" and your acronyms correctly. Add anything that matters, including "dembrane" itself. - *Anonymise transcripts* - strip identifying details so what's stored can be shared without exposing who said it. > [!TIP] > These two are the highest-leverage fields. Key terms sharpen every transcript in the project; > anonymisation is a privacy decision best made before you collect. Set both before you print > the QR code. ## What you ask participants for - *Ask for name* and *ask for email* - whether onboarding collects each. Email is handy for sending a report or updates. Both are off unless you switch them on, keeping the [no-account](./portal-and-participant-experience.md) experience light. ## What dembrane generates - *AI title & tags* - let a language model name and tag each conversation, so a long list stays navigable without manual filing. - *Get Reply* - an audio-reply mode where dembrane responds to a participant, with its own mode and prompt so you control the tone. ## Verification Let participants confirm what was drawn from their conversation - the participant, not the model, decides how they're represented. Turn *verification* on, choose whether it shows on the finish flow, and pick the *topics* (predefined or custom) people are asked to confirm. ## Notifications and tags Offer participants a *subscription* to updates - great for post-event follow-up, since people who leave an email get notified when reports are ready. And define the *tags* available for conversations in this project. ## Preview, then share A *live preview* shows the portal as you change settings, so you see exactly what a participant gets. When you're happy, generate the *QR code and invite link* - print the QR for a venue, or send the link by email. Both open the same [participant portal](./portal-and-participant-experience.md). > [!NOTE] > Changes here affect *new* conversations from that point on. If you change key terms or turn on > anonymisation after collecting, you can [re-transcribe](./transcription.md) existing > conversations to apply it. ## Why each setting exists (intent) Every field is here to steer one downstream behaviour. Knowing what a setting *drives* tells you when to touch it and when to leave it. This is also the reference the project onboarding assistant reads when it suggests changes. - *Context* (project setting, not on this screen but the most important field): the purpose, audience and what you want to learn. It steers chat answers, report framing and the assistant's suggestions. Vague context weakens everything downstream, so write 2-5 real sentences. - *Language*: sets the language of the intro screens only. Its intent is the participant's first impression, not transcript language. Match it to who you're inviting. - *Default conversation title / description / finish text*: the participant's framing before, during and after. Intent is clarity and trust - the finish text should say what happens with their contribution, so write it for a person, in their language. - *Key terms* (`transcript_prompt`): the intent is transcript accuracy. These names and jargon feed the transcription cleanup pass, so anything spelled wrong here stays wrong in every transcript. Highest-leverage field for data quality. - *Anonymise transcripts*: a privacy decision that changes what is stored. Set it before collecting; its intent is making transcripts shareable without exposing who spoke. - *Ask for name / email*: intent is post-event contact and report delivery, traded against keeping onboarding light. Only turn on what you will use. - *AI title & tags*: intent is navigability of a long conversation list, not analysis. Safe to leave on. - *Get Reply*: intent is giving participants a response in the moment; the mode and prompt exist so you control tone. Only enable when you have decided what that reply should feel like. - *Verification*: intent is participant agency - they, not the model, confirm how they're represented. Enable when representation accuracy matters more than a shorter finish flow. - *Subscription*: intent is follow-up - people who leave an email hear when reports land. ## Related - [The participant portal](./portal-and-participant-experience.md) - the experience these settings produce. - [Transcription](./transcription.md) - how key terms and anonymisation feed the cleanup pass. - [Projects](./projects.md) - the project these portal settings belong to. --- # dembrane Go (the mobile app) dembrane Go is the native iOS app for the person in the room - walking a venue, moving between tables, recording conversation after conversation on a phone. It records *locally first*, keeps going in the background, and uploads to the same project you'd see on the [dashboard](./projects.md). On background-recording resilience it's actually *ahead* of the web. > [!IMPORTANT] > dembrane Go is in *beta* - it isn't on the App Store yet. We're inviting a small group of > testers through TestFlight while we finish it. Want to be one of them? Email > [sameer@dembrane.com](mailto:sameer@dembrane.com) and we'll get you set up. You sign in with your email and password (two-factor supported), into the same workspaces and projects as the web. What you can do still follows your [workspace role](./roles-and-permissions.md), and recording counts towards your [metered hours](./tiers-and-billing.md). ## What it does *Records, robustly.* Audio is captured to the device and uploaded as it goes, so a recording survives a crash or the app being killed - the audio is already on disk. It keeps recording in the background while you do other things, a Live Activity / Dynamic Island indicator shows a recording in progress without the app open, and a live waveform plus mic selector let you confirm audio and pick the input (e.g. an external mic). You can also import an existing audio file instead of recording live. *Read and manage conversations.* Open one to read its [transcript and summary](./conversations-and-transcripts.md), generate a title, manage tags, edit, move, delete, and re-transcribe - the day-to-day actions, on mobile. *Ask questions.* [Ask across your conversations](./chat-and-ask.md) from the phone, with templates, history, sources, and a picker for which conversations a question draws on. Plus fast on-device search to find one without scrolling. *Edit portal essentials.* Adjust the project's title, description and key terms in [the portal](./portal-editor.md), and share the *QR code* off your screen so a participant can scan straight away. *Account.* Switch the active project, sign out, and start account deletion (which completes in the browser). ## When to use Go vs the web | Reach for dembrane Go when… | Reach for the web when… | |---|---| | You're recording in person and on the move | You're sitting down to analyse | | Connectivity is shaky and you can't lose audio | You need the full analysis surface | | You want hands-free background capture | You're building reports or a custom library | | You want to share a QR code off your screen | You're setting up a project or managing people | ## What's web-only Go is a focused recorder-and-reader, not the whole dashboard. These live on the web: - [Library & analysis](./library-and-analysis.md) - extracted topics, aspects and quotes. - [Reports](./reports.md) - the multi-section report builder. - The full participant [verification](./portal-editor.md) configuration (Go does the host-side essentials). - Project creation, and all workspace / organisation / team management. - Billing detail, webhooks, export, and the host guide PDF. > [!TIP] > A common pattern: collect on dembrane Go in the room, then switch to the > [dashboard](./projects.md) afterwards to build the [library](./library-and-analysis.md) and > [report](./reports.md). They share the same data - what you recorded on the phone is already > in the project on the web, nothing to sync. ## Related - [Recording](./recording.md) - the capture mechanics dembrane Go shares with the web. - [Conversations & transcripts](./conversations-and-transcripts.md) - what you read and manage in the app. - [Chat & Ask](./chat-and-ask.md) - asking questions of your conversations from the phone. - [The portal editor](./portal-editor.md) - the portal settings you can edit on the go. --- # Conversations & transcripts A *conversation* is one recording (or one piece of typed text) someone contributed to your project. Once the audio is [transcribed](./transcription.md), you can read it, copy it, summarise it, tag it, and feed it into [chat](./chat-and-ask.md), [the library](./library-and-analysis.md), and [reports](./reports.md). Open a project and go to *Conversations*. You get one row per recording: its title, where it came from, how far it's got through processing, and any tags. Open a row to read the full transcript and act on it. Everyone who can see a project can read and download conversations; deleting needs *owner*, *admin* or *member* (see [roles & permissions](./roles-and-permissions.md)). Reading transcripts is in every plan, including [Free](./tiers-and-billing.md) - the tiers only gate what you do *on top* of them (chat, library, reports). ## The conversation list Each row shows: - *Title* - typed by the participant, set by you, or generated by a language model if you turned that on in the [portal editor](./portal-editor.md). - *Source badge* - *portal audio* for spoken recordings, *portal text* for typed submissions. Tells you at a glance whether there's audio behind a row or just text. - *Status* - uploading, transcribing, summarising, or finished (see [transcription](./transcription.md)). - *Tags* - any [project tags](#tags) applied. Use *search* and *filters* to narrow a big project by tag, status, or text. > [!TIP] > If you offered both a "speak" and a "type instead" route, source badges let you see the mix > of spoken vs typed contributions without opening every row. ### Bulk actions Select several rows to act on them together: - *Move* - send them to another project (or a workspace you can access). Handy when recordings landed in the wrong place. See [data ownership & compliance](./data-ownership-and-compliance.md) for what moving means across workspace boundaries. - *Lock* - mark them read-only so they're not edited during analysis. - *Delete* - permanent; see [the warning below](#delete). - *Retranscribe* - re-run [transcription](./transcription.md), for example after improving your key-terms prompt in the [portal editor](./portal-editor.md). > [!IMPORTANT] > Bulk delete and retranscribe hit *every* selected row, and there's no undo. Check the > selection count before you confirm. ## Reading a conversation Open any row for the full transcript. *Transcript.* Recordings are captured and transcribed in short *chunks* (roughly half-minute pieces, so a recording survives a crash or dropped connection). You read the transcript as those chunks, in order - which also makes it easy to point at exactly where something was said, and to [retranscribe](#retranscribe) just the part that came out poorly. *Copy.* Copy the transcript (or a part) to paste into notes, an email, or another tool. To get transcripts out in bulk, use the project-level [export](./export-and-data-portability.md). *PDF download.* Download one conversation as a tidy, shareable PDF - the right tool for handing a single interview to someone without dashboard access. For many at once, use [export](./export-and-data-portability.md). *Summary.* Most conversations are summarised automatically when transcription finishes. You can *generate* one if it's missing, or *regenerate* it after a retranscribe or if the first pass missed the point. Lighter [chat](./chat-and-ask.md) and [report](./reports.md) passes read from the summary, so keeping it accurate pays off downstream. > [!NOTE] > A summary is a language model's reading of the transcript - a starting point, not the final > word. dembrane surfaces what's in the room; the judgement about what matters stays with you. ### Tags Apply *project tags* to group conversations - by table, theme, location, session, whatever your project needs. Tags drive the [list filters](#the-conversation-list) and let you scope [chat](./chat-and-ask.md) to a subset. You can also offer some tags to participants to pick at the start of their recording; set those up in the [portal editor](./portal-editor.md). ### Verified artifacts If you enabled *verification* in the [portal editor](./portal-editor.md), participants review and approve the key points a language model pulled from their own words. Those *verified artifacts* are participant-checked, so they carry more weight than an unreviewed extraction. See [the participant portal](./portal-and-participant-experience.md) for the participant's side. ### Lock *Lock* a single conversation to make it read-only - once a round of collection is done, or before you share a project widely. You can also lock in bulk from the [list](#bulk-actions). ### Anonymisation If you turned on *anonymise transcripts* in the [portal editor](./portal-editor.md), personal details are redacted as the transcript is processed, and the conversation shows its *anonymisation status*. See [data ownership & compliance](./data-ownership-and-compliance.md). > [!IMPORTANT] > Anonymisation happens during processing, not retroactively. Turn it on in the portal editor > *before* you collect, so it's applied as recordings come in. ### Retranscribe Re-run [transcription](./transcription.md) on a conversation when: - the audio was fine but the transcript has errors a better *key-terms prompt* would fix (set key terms in the [portal editor](./portal-editor.md), then retranscribe); - a chunk failed or came back empty; - you changed anonymisation and want it reapplied. Retranscribing replaces the transcript, so regenerate any earlier summary afterwards (see [reading a conversation](#reading-a-conversation)). ### Delete Delete a single conversation from its detail page. > [!WARNING] > Deleting can't be undone - it removes the recording and its transcript. To just keep one out > of analysis, [lock](#lock) it or move it to an archive project instead. Only *owner*, > *admin* and *member* can delete; *external* and *observer* cannot. ## Feeding everything else Conversations are the raw material for the rest of dembrane: - *[Chat & Ask](./chat-and-ask.md)* - ask questions across a chosen set, with cited sources. - *[Library & analysis](./library-and-analysis.md)* - extracted topics, aspects and quotes across many conversations at once. - *[Reports](./reports.md)* - assemble findings into something you can share. The cleaner your conversations - sensible titles, consistent tags, accurate transcripts - the better all three work. ## Related - [Transcription](./transcription.md) - how audio becomes text, and what the status stages mean. - [Chat & Ask](./chat-and-ask.md) - ask questions across your conversations. - [Library & analysis](./library-and-analysis.md) - extracted topics, aspects and quotes. - [Reports](./reports.md) - assemble and share findings. - [The portal editor](./portal-editor.md) - set titles, tags, key terms, anonymisation and verification before you collect. - [Export & data portability](./export-and-data-portability.md) - get transcripts out in bulk. - [Roles & permissions](./roles-and-permissions.md) - who can read, delete and lock. - For a host's walkthrough, see [transcripts & conversations](../users/host/transcripts-and-conversations.md). --- # Notifications Notifications tell you something happened without making you go looking for it. They arrive in two places - the dashboard bell and your *email* - and dembrane is deliberately quiet: it batches email so a busy day doesn't bury you in one-line alerts. Everyone with an account can receive them. Some, like workspace-request alerts, are aimed at [admins](./roles-and-permissions.md) who can act on them. You manage what you receive in your [account & security](./account-and-security.md) settings. ## In-app vs email The dashboard bell is *always immediate* and shows everything in real time. Email is the gentler channel, where the batching below kicks in. If you want the full, immediate picture, check the bell. ## Digest batching dembrane doesn't email you every event the moment it happens: - The *first 5 notifications in a rolling 24-hour window* are emailed *individually* - the ones you most likely want straight away. - After that, the rest are *rolled into a daily digest* sent once a day at *09:00 UTC*. So a normal day sends a handful of timely emails; a very busy day sends those plus a single morning summary, instead of dozens of separate messages. ## What you'll be notified about *Workspace requests.* When someone asks to *create a workspace* or *upgrade a tier*, the admins who can approve it are notified, in-app and by email (within the batching rules). This is the free-tier upgrade flow; admins act on it in the dashboard, and staff see it under [upgrade requests](../users/staff/upgrade-requests.md). *Tier expiry.* If a workspace's tier is set to expire - a time-limited trial, say - dembrane sends a *prewarning three days before* it lapses, so there's time to renew or plan rather than discovering it after the fact. ## Subscribing and unsubscribing - *Preferences* live in your [account & security](./account-and-security.md) settings. - *Email* notifications can be unsubscribed from - every email includes the means to opt out of that kind. - Some notifications are also surfaced as *portal* subscription options for participant reports, configured separately in the [portal editor](./portal-editor.md). > [!NOTE] > Unsubscribing from emails doesn't silence the bell - you'll still see notifications in the > dashboard. The two channels are managed independently, so you can stay informed without a > noisy inbox. ## Related - [Account & security](./account-and-security.md) - where you manage notification preferences. - [Upgrade requests (staff)](../users/staff/upgrade-requests.md) - the workspace-request flow behind those alerts. - [Tiers & billing](./tiers-and-billing.md) - what tier expiry means and how to renew. --- # Webhooks & integrations A *webhook* lets dembrane tell *your* systems the moment something happens - a conversation started, a transcript finished, a summary completed, a report generated. Instead of polling dembrane to ask "is it done yet?", you register a URL and dembrane sends it a signed message when the event occurs. That's how you wire dembrane into the rest of your stack: a Slack alert when a report is ready, a database row when a conversation is transcribed, a downstream job kicked off when a summary lands. Webhooks are a *Changemaker-and-above* feature, gated on the [tier](./tiers-and-billing.md). Within an eligible workspace, managing them sits with [admins](./roles-and-permissions.md). On Free and Innovator workspaces the integrations tab won't offer them. ## The four events - `conversation.started` - a participant or host has begun a conversation. - `conversation.transcribed` - a conversation's audio has been transcribed. - `conversation.summarized` - a conversation has been summarised. - `report.generated` - a [report](./reports.md) has finished generating. Each event carries the identifiers your system needs to know *which* conversation or report it's about, ready for you to fetch the detail (or [export](./export-and-data-portability.md) it) if you need more. ## Adding and testing one Webhooks live in a project's *integrations* tab: 1. *Create* a webhook by giving dembrane a URL and choosing which events it should receive. 2. *Test* it - dembrane sends a test payload to your URL so you can confirm your endpoint receives and parses it before relying on it. 3. There's a *copyable* form of the configuration to make setup in your own tooling straightforward. The endpoints (`GET/POST/PATCH/DELETE /api/projects/{pid}/webhooks`, plus `/test`) are documented on [webhooks](../users/developer-external/webhooks.md). ## Verifying the signature So your endpoint can trust a request really came from dembrane, each webhook is signed. Set a *secret* on the webhook, and dembrane computes an *HMAC-SHA256* signature over the payload and sends it in the `X-Dembrane-Signature` header. Your endpoint recomputes the same HMAC with the shared secret and compares - if they match, the request is authentic. > [!WARNING] > Always verify the `X-Dembrane-Signature` before acting on a webhook. A webhook URL is > reachable from the internet by nature; the signature is what proves the caller is dembrane > and not someone who guessed your URL. ## The integrations tab The integrations tab is a project's connection point to the world outside dembrane. Webhooks *push* events to you; [export](./export-and-data-portability.md) - transcript zips and CSV/Excel - lets you *pull* data on demand. Both live here. ## Related - [Webhooks (developer)](../users/developer-external/webhooks.md) - the endpoints, payloads, and signature-verification detail. - [Tiers & billing](./tiers-and-billing.md) - webhooks need Changemaker or above. - [Export & data portability](./export-and-data-portability.md) - the other half of the integrations tab: pulling data out. - [Reports](./reports.md) - the source of the `report.generated` event. --- # MCP & bring-your-own-LLM On the *Innovator* tier you can connect your own language model to dembrane instead of using dembrane's built-in analysis. Instead of dembrane doing the analysis, the [Chat & Ask](./chat-and-ask.md) screen becomes an integration point: you connect *your* assistant - ChatGPT, Claude - over *MCP* (the Model Context Protocol) and ask your own model questions about your conversations. It's for people who already have a model they trust and want dembrane to be the *source of conversation data* rather than the analyst. > [!IMPORTANT] > Innovator's BYO-LLM and MCP are *coming soon* - Innovator as a self-serve tier is gated on > the MCP integration shipping. Today, *Changemaker* includes analysis, > which has it built in. See [tiers & billing](./tiers-and-billing.md) for current > availability. ## Analysis by tier | Tier | Analysis | |---|---| | *Free* | No analysis - secure transcription only | | *Innovator* | *Bring your own LLM + MCP* - connect ChatGPT/Claude; dembrane provides the data, your model does the thinking *(coming soon)* | | *Changemaker* | *Built-in analysis* on EU-hosted *Gemini* - [chat](./chat-and-ask.md), the [library](./library-and-analysis.md), and [reports](./reports.md) all work out of the box | | *Guardian* | Built-in analysis on a fully *EU-sovereign* stack *(coming soon)* | The shape matters more than it first looks: - On *Free*, you get transcription you can read and [export](./export-and-data-portability.md), but no analysis. - On *Innovator*, the analysis happens in *your* model - dembrane gives it access to your conversations; the reasoning is yours. - On *Changemaker*, dembrane runs the analysis itself on EU-hosted Gemini - no setup, no external model to connect. - On *Guardian*, the same built-in analysis runs on sovereign European infrastructure for the most sensitive work. ## What MCP gives you The Model Context Protocol is an open standard for connecting assistants to data and tools. With dembrane's MCP integration, an assistant like ChatGPT or Claude can reach into your project and work with your conversations - listing them, searching them, reading transcripts - so you can ask your own model questions grounded in what people actually said. Because dembrane stays the system of record and your model does the analysis, you keep the model relationship, and its data handling, on your terms - true to dembrane's view that *people know how*, and the model is a tool in service of that. > [!NOTE] > The `.mcp.json` you may spot in the open-source repository is for dembrane's own internal > tooling. It is *not* the customer-facing dembrane MCP server described here - that's the > integration coming with Innovator. ## Where things stand - *Changemaker built-in analysis* - available now, self-serve, on EU-hosted Gemini. - *Innovator BYO-LLM + MCP* - *coming soon*, gated on the MCP integration shipping. - *Guardian EU-sovereign analysis* - *coming soon*, gated on the sovereign stack. If you need analysis today, Changemaker is the route. If bring-your-own-model matters to you, tell your dembrane contact so we know to flag you when Innovator opens. ## Related - [Chat & Ask](./chat-and-ask.md) - the analysis surface that becomes a BYO-LLM/MCP integration on Innovator, and works built-in on Changemaker. - [Tiers & billing](./tiers-and-billing.md) - what each tier unlocks and current availability. - [MCP & bring-your-own-LLM (developer)](../users/developer-external/mcp-and-byo-llm.md) - the developer and self-hoster view. - [Data ownership & compliance](./data-ownership-and-compliance.md) - the Guardian sovereign stack and dembrane's EU posture. --- # 5 ways to use dembrane dembrane is a set of building blocks designed to support dialogue and deliberative processes. Facilitators and process designers can pick and choose the blocks (or layers) they need, leaving the rest. At its foundation, dembrane is a secure record-keeper. As you climb to higher layers, the feedback loop gets tighter and faster, moving from a broad look back over a whole process to a targeted question inside an active conversation. --- ## The Five Layers of dembrane ### 1. RECORD: Looking back on a whole process * **What it does:** Turns any number of participant phones into a secure system of record. Every conversation is securely recorded, transcribed with state-of-the-art models, and stored centrally on encrypted servers. * **Participant Relation:** Most participants consent to being recorded when framed clearly as optional, secure, and privacy-safe. * **What it takes:** Facilitation remains unchanged. The host sets up a project, establishes anonymization and keyword rules, secures informed consent, and scans a QR code to start recording. ### 2. ASK: Looking back on a session * **What it does:** Merges, structures, and de-duplicates what was said across multiple tables simultaneously into a cohesive first draft of outcomes or recommendations. It can also identify blind spots (e.g., highlighting groups mentioned as rhetorical devices who are not present). * **Participant Relation:** Participants appreciate seeing hundreds of hours of discussion synthesized into concrete takeaways, provided it is presented in their own words rather than as a machine verdict. * **What it takes:** Introduce a synthesis step to generate the merged draft, then bring it back to the participants to validate and inspect. ### 3. VERIFY: Looking back on a conversation * **What it does:** Closes the feedback loop while the conversation is still warm. dembrane drafts a live table summary and hands it back to the participants right in the room so they can correct it and sign off on what gets saved. * **Participant Relation:** Tends to land very well because it respects participants' authority over their own words. People appreciate being asked "did we get you right?" and will actively correct the record. * **What it takes:** Design a 5-minute live review moment at each table to read the summary back, critique it, and correct any missed threads or connections. ### 4. EXPLORE: Looking forward inside a live conversation * **What it does:** Listens to the friction or circles in an ongoing conversation and, when prompted, offers a sharp, Socratic question to break through performance and deepen the dialogue. * **Participant Relation:** A timely, sharp question is felt as a gift that opens up the conversation; a clumsy or ill-timed one can feel like a gimmick. It only lands when the conversation is already alive. * **What it takes:** Brief participants on the option and determine where a live question might add value. Highly experimental, and particularly useful in unfacilitated or self-guided settings. ### 0. SHARE: Looking across processes (Data Commons) * **What it does:** Pools anonymized deliberative data into a governed data commons, enabling researchers and practitioners to analyze what makes deliberation and collective decision-making work across different contexts and countries. * **Participant Relation:** In many contexts, participants are honored that their words will have an impact beyond their local room. In others, it is an unacceptable risk. Stakeholder check-in is vital. * **What it takes:** Fully opt-in, with a separate data-sharing agreement and clear participant notice. --- ## Design Philosophy * **Design for Friction:** dembrane is not a way out of the hard parts of deliberation. The hard work of deliberating remains entirely with the people. The platform chooses *not* to optimize for friction-free machine conclusions, but rather to use friction (like the VERIFY step) to keep human participants in complete authority over their own words. * **Pick and Choose:** Process designers should walk through these five layers to see which ones earn their place in a specific process, turning on only the exact features required. --- # dembrane next *dembrane next* is the staging version of dembrane. Every change that merges to the main branch deploys there straight away; production updates on a tagged release roughly every two weeks. So some things are usable on dembrane next before they reach the production app most people use. Anywhere in these docs you see *dembrane next only*, the feature works on dembrane next but is **not yet in production**. This page is the running list of what that covers right now, so you always know whether something you read about is actually available to you. > [!NOTE] > You're almost certainly on production (`dashboard.dembrane.com`). If a feature below > isn't showing up for you, that's expected - it hasn't shipped yet, it isn't a bug. ## On dembrane next right now | Feature | What it is | Where | |---|---|---| | *The new Ask experience* | Ask opens as a home for your chats with one question bar, and the assistant works in steps - searching, reading transcripts, checking live status, answering from the docs, and proposing settings changes for your review - with named citations and a Stop control. The classic Specific Details chat stays one click away. | [Chat & Ask](./chat-and-ask.md#one-question-bar) | | *Assistant memory & context* | The assistant saves notes (you view and remove them in user, project, and workspace settings) and takes standing guidance from a workspace-wide *assistant context*. | [Account & security](./account-and-security.md#what-the-assistant-remembers-about-you), [managing your workspace](../users/host/managing-your-workspace.md#give-the-assistant-standing-context) | | *The Monitor* | A live view of a session: the participant flow from QR scan to recording, live recordings with audio warnings, and transcription progress. | [The live monitor](./live-monitor.md) | | *The living canvas* (beta) | A live page the assistant builds and regenerates during a session. Off by default for every project: a host opts a project in with the *Living canvas* switch under *Experimental* in project settings. | [The SMART loop](../building/smart-loop.md) | If the table is short, that's a good sign: most of dembrane is the same on next and production. Only genuinely in-progress features live here. ## How this list stays honest The source of truth is the per-environment flags in the frontend config (`frontend/src/config.ts`), where a *dembrane next only* feature reads as `byEnv({ next: true }, false)` - on for next, off everywhere else. At each production release (tagged from main, ~every two weeks), this page is reviewed: anything whose flag has widened to production *graduates* - it comes off this list and its *dembrane next only* tag is dropped from the main docs. So when a feature "goes out of next", the docs follow. ## Related - [Chat & Ask](./chat-and-ask.md) - where agentic mode lives. - [Chat & Ask - for hosts](../users/host/chat-and-ask.md) - the host walkthrough. - [The documentation map](../map.md) - everything else. --- # Building now These pages describe features that are *being built* - most are not available yet, not even on [dembrane next](../features/dembrane-next.md); where an early piece has reached beta, the page says so. Each one is written as a user story before the first line of code, and the build isn't done until the story works end to end. Why publish them? Three reasons: - You can see where dembrane is going, and tell us early if a story misses your reality. - The in-app assistant reads these docs. When you ask it for something that's on this list, it can say *"that's being built right now"* instead of a flat no - and capture exactly what you need from it. - It keeps us honest. When a feature ships, its story graduates into the main documentation and gets the *dembrane next only* tag until it reaches production. ## In progress - [The SMART loop](./smart-loop.md) - a living canvas the assistant regenerates through your session: live frames and answers on a rhythm, versions kept, improved by chat. The canvas is now in *beta* on dembrane next - off by default, and a host opts a project in with the *Living canvas* switch under *Experimental* in project settings. Not in production yet. ## Related - [dembrane next](../features/dembrane-next.md) - features that are built and live on the preview environment. - [The documentation map](../map.md) - everything else. --- # Troubleshooting transcripts & summaries dembrane turns spoken words into text and clear, high-level summaries. Usually, this happens within a minute of the recording ending. If a transcript came out rough, a summary missed the point, or you are wondering why a conversation is empty, these are the steps to fix them. ## 1. The transcript contains errors or is hard to read Transcription quality is highly dependent on audio clarity and vocabulary context. If proper nouns, names, or industry-specific terms are being misspelled or misheard: ### Step 1: check and update your project's key terms The single most effective tool for better transcription is your *Key Terms* list in the project or portal settings. - Navigate to your project settings or the portal editor. - Add the proper nouns, participant names, project abbreviations, and industry terms (e.g., specific software names, local places, or technical jargon) that people are likely to mention. - *Tip: If you're running a session about a specific topic, pre-populate these terms before people start speaking.* ### Step 2: retranscribe the conversation Once your Key Terms list is updated, you can reprocess the audio to generate a better transcript: - Open the conversation in your dashboard. - Click the *Retranscribe* button (the refresh action icon next to the transcript title). - Confirm the settings in the modal and start the retranscription. - *This creates a new, corrected conversation with the improved transcription while leaving your original recording intact.* --- ## 2. The summary is inaccurate, outdated, or generic Summaries are generated by language models that analyse the transcribed text. If a summary isn't helpful, it is usually because the underlying transcript was inaccurate or the language model needed more guidance on what to prioritise. ### Step 1: make sure the transcript is right If the transcription was rough, follow the steps above to *retranscribe* it with proper Key Terms first. A summary can only be as accurate as the text it is summarising. ### Step 2: define your project's goal and methodology The language model uses your project's *Goal* and *Methodology* to guide what it should look for and emphasise in its summaries. - Check your project's overview or settings to make sure your Goal is clear. - Adjust the Goal if you want the summary to focus on specific themes or questions. ### Step 3: regenerate the summary If you've corrected the transcript or adjusted your project goals, you can get a fresh summary: - Open the conversation in your dashboard. - Next to the *Summary* heading, click the *Regenerate* button (the refresh/retry icon). - Confirm the regeneration. The language model will discard the old summary and write a fresh one based on the current transcript and project context. --- ## 3. The transcript or summary is empty If a conversation shows up in your dashboard but has no text or summary, don't panic. Check these common states: - *Give it a minute:* A conversation shows up immediately when recording finishes, but transcription and summary generation take between *30 seconds and a minute* to complete. Refresh the page after a short wait. - *Check the "Empty" badge:* If the conversation is flagged with an "Empty" badge, it means no speech was detected in the audio file (e.g., if a participant accidentally submitted a silent recording or had microphone issues). - *Processing is stuck:* If several minutes have passed and the conversation is still loading or has no transcript, a processing chunk may have failed. You can safely try to *Retranscribe* the conversation to restart the pipeline, or email *support@dembrane.com* if the problem persists. ## Related - [Transcripts & conversations](./transcripts-and-conversations.md) - [Collecting conversations](./collecting-conversations.md) - [Setting up the portal](./portal-editor.md) --- # Chat & Ask (for hosts) Ask is your interactive deep-dive into a [project](../../features/projects.md). You type a question in plain language and dembrane answers from the conversations you've collected, pointing back to where each part came from. It doesn't replace reading transcripts - it helps you find what's worth reading. The answers come from your participants; the model's job is to find and organise what they said, with receipts. The full mechanics live in the canonical [Chat & Ask](../../features/chat-and-ask.md) reference. ## Run a good deep-dive The pattern that works: start broad, then zoom in, then ask for evidence. 1. Click *Ask question* (or *New chat*) in your project. 2. Start broad: *"What are the main themes?"* 3. Zoom in: *"What concerns came up about the bus route?"* 4. Ask for evidence: *"Show me the quotes."* Each chat is a thread - read the answer, then follow up: *"say more about the second point"*, *"who said that?"*, *"now just the under-30s"*. Old chats stay in your history. This is the right tool for comparing viewpoints, finding quotes, or testing a hunch. ## One place to ask > [!NOTE] > The new Ask experience is live on *[dembrane next](../../features/dembrane-next.md)* and > reaches production with the next release. Ask opens as a home for your chats, with one input: *Where would you like to start?* Type your question and press Enter, and the assistant gets to work in steps - searching your conversations, reading [transcripts](../../features/conversations-and-transcripts.md), and chaining what it finds to answer harder questions (*"find every conversation where someone disagreed with the proposal and tell me why"*). Typing in the same bar also filters your earlier chats, so it's how you find last week's thread too. A *Templates* menu inserts a saved prompt. You watch the assistant's progress as it works, and *Stop* replaces *Send* so you can halt a run mid-way. Answers cite sources by name - *"Maria's conversation"* - and each link jumps to the exact spot in the transcript. ## The classic chat: Specific Details Prefer to pick the conversations yourself? One click on *Prefer the old chat? Start a Specific Details chat* starts a classic chat: you choose the conversations (one, a few, or all of them) and dembrane answers in one pass with exact quotes and citations from the full transcripts. Reach for this when every answer should come from the same fixed set - say, while drafting a report. If you're already viewing one conversation when you start, it's selected for you. > [!TIP] > Map the territory by asking the assistant first, then start a *Specific Details* chat > narrowed to the right conversations once you know which thread to pull. The old *Overview* mode has been retired: its job - themes and patterns across all your conversations - is now just a question you ask the assistant. ## Check the sources Every answer links back to the conversations it drew on. Glance at them: they let you check the answer against what people actually said, jump to the [transcript](../../features/conversations-and-transcripts.md) for full context, and quote a participant accurately. If an answer feels too neat, open the sources. The transcripts are the truth; the chat is a way in. ## Templates and the prompt library You don't have to write every question from scratch. Templates are pre-written prompts for common jobs - pulling out themes, listing concerns, summarising one topic. Built-in ones ship in the chat; you can save your own when you reuse a prompt across projects. There's also a prompt library with more to copy. Pick one, adjust the wording to your project, send. They're a starting point, not a cage. ## Tips for good questions - Ask one thing at a time. *"What were the top three concerns?"* beats a five-part paragraph. - Name the scope when it matters: *"in the Tuesday sessions, …"*. - Give the project good [context](./creating-a-project.md) - the model uses it as background, so honest, specific context sharpens every answer. - Check the sources before you act on an answer. ## More than analysis The assistant does more than answer questions about your data: - Ask *"is anyone recording right now?"* and it checks the same live status as the [Monitor page](./collecting-conversations.md#watch-the-room-the-monitor-page). - Ask *"how do I set up verification?"* and it answers from this documentation, linking the page it used. - Ask it to improve your setup and it *proposes* settings changes - you review and apply each one; it never changes your project by itself. - If you're stuck, it can [log a question with the dembrane team](./getting-help.md). It also *remembers*: it can save notes about how you like to work and what the project is about, so your next chat starts smarter. You stay in charge of that memory - see and remove your own notes under *Settings → Assistant*, project notes in project settings, and workspace notes in [workspace settings](./managing-your-workspace.md#give-the-assistant-standing-context). ## What your plan gives you | You're on | Chat & Ask gives you | |---|---| | *Free* | Chat is gated under free-tier limits. | | *Innovator* | No built-in analysis; the chat screen becomes a bring-your-own-LLM + MCP integration (*coming soon*). | | *Changemaker* | Built-in analysis on EU-hosted Gemini - the usual home for hosts doing analysis. | | *Guardian* | As Changemaker, on an EU-sovereign stack (*coming soon*). | If you hit a wall, that's a tier limit, not a bug. See [tiers, billing & usage](./tiers-billing-and-usage.md) for how to upgrade. ## Related - [Chat & Ask - feature reference](../../features/chat-and-ask.md) - the canonical how-it-works page. - [Conversations & transcripts](../../features/conversations-and-transcripts.md) - what chat reads, and where sources point. - [Library & analysis](./library-and-analysis.md) - the other way to make sense of a large set of conversations. - [Reports](./reports.md) - turn good answers into something you can share. - [Tiers, billing & usage](./tiers-billing-and-usage.md) - what each plan unlocks. - [MCP & bring-your-own-LLM](../../features/mcp-and-bring-your-own-llm.md) - connect your own model on Innovator (*coming soon*). - [dembrane next](../../features/dembrane-next.md) - preview features (like the new Ask experience) that aren't in production yet. --- # Library & analysis (for hosts) The library is dembrane reading across all the conversations in a [project](../../features/projects.md) at once and laying out what it found: the topics that came up, the aspects within each, and the quotes that ground them. Where [Chat & Ask](./chat-and-ask.md) answers a question you bring, the library answers the one you haven't thought to ask - *"what's actually in here?"*. Reach for it on large datasets - dozens of conversations from a multi-table town hall, a long run of interviews, anything past what you'd sit and read. For a handful, reading the [transcripts](../../features/conversations-and-transcripts.md) or asking a few [chat](./chat-and-ask.md) questions is quicker. The full mechanics live in the canonical [Library & analysis](../../features/library-and-analysis.md) reference. ## Living canvas (Experimental Beta) The *living canvas* (and the Project Library analysis that drives it) is currently in *Beta* and gated behind a project-level toggle. Because it is experimental, this setting is currently available only in the next-release (*echo-next*) environment, and is not visible in production. To enable the living canvas for your project on *echo-next*: 1. Open your project and click the settings gear next to your project name. 2. In the settings panel, scroll to the *Experimental* section. 3. Turn on the *Living canvas (Beta)* toggle. Once enabled, the *Library* tab in your project sidebar will become available, and your workspace can begin using board primitives, interactive brief-driven extractions, and chat-to-canvas edits. ## Generate it Open your project and go to *Library*. If it hasn't been built, generate it - dembrane reads the conversations and extracts the structure. This takes a little time, proportional to how much you've collected; you'll see its status while it runs. Two things: - Collect first, then generate. The library reflects what's in the project the moment you build it - run it once you've got a meaningful body of conversations, not after the first. - You can regenerate. As more conversations arrive, or after you sharpen the project's context, regenerate to pick up the new material. > [!TIP] > Give the project a clear, honest [context](./creating-a-project.md) before generating. The > model uses it as background, so good context produces a sharper library. ## Read it: views, aspects, quotes The library is laid out broad to specific: - *Views* - a lens onto the conversations. dembrane builds a default view; create custom views to look at the same material through a different frame (say, organised around one question you care about). Handy when you want the analysis to line up with a [report](./reports.md)'s shape. - *Aspects* - within a view, the distinct topics that came up. - *Quotes* - within an aspect, participants' own words. These are the point: they keep the analysis honest and traceable. Drill from a view into an aspect into its quotes. From any quote you can jump back to the [conversation](../../features/conversations-and-transcripts.md) it came from to read the surrounding context. ## From library to report The library and [reports](./reports.md) work hand in hand: use the library to find the themes and quotes, a report to present them. Generate the library, pick the aspects worth surfacing, note their best quotes, then build a report around those. You can cross-check anything with a targeted [chat](./chat-and-ask.md) question - *"show me everyone who raised this"* - before you commit it. ## What your plan gives you The library is built-in analysis, so it follows the analysis tier. | You're on | The library | |---|---| | *Free* | Not included - gated, with an upgrade route. | | *Innovator* | Not included (no built-in analysis). | | *Changemaker* | Included - built-in analysis on EU-hosted Gemini. | | *Guardian* | Included, on an EU-sovereign stack (*coming soon*). | If the library is gated, that's a plan limit, not an error - see [tiers, billing & usage](./tiers-billing-and-usage.md) to upgrade. If it isn't available to your workspace at all, you'll see a *contact sales* prompt rather than a self-serve upgrade. ## Related - [Library & analysis - feature reference](../../features/library-and-analysis.md) - the canonical how-it-works page. - [Chat & Ask](./chat-and-ask.md) - ask targeted questions of the same conversations. - [Reports](./reports.md) - present the themes and quotes the library surfaces. - [Conversations & transcripts](../../features/conversations-and-transcripts.md) - where every quote leads back to. - [Tiers, billing & usage](./tiers-billing-and-usage.md) - what each plan unlocks, and how to upgrade. --- # Reports (for hosts) A report is dembrane's automatic synthesis of a project - the quickest way to capture the atmosphere and the main questions and hand them back in a form a busy stakeholder will actually read. Best for a council that wants a written summary after a town hall, a findings document for the team, or a funder's end-of-engagement write-up. It's the natural home for everything you found in [chat](./chat-and-ask.md) and the [library](./library-and-analysis.md): themes, quotes, answers - gathered, ordered, presented. The full mechanics live in the canonical [Reports](../../features/reports.md) reference. ## Build a report Open your project and go to *Reports*. dembrane analyses all the conversations (a few minutes) and drafts the report from sections - each a focused piece: an overview, a theme, a question, a recommendation. A practical order: 1. Decide the shape. What does the reader need - an executive summary, a theme-by-theme breakdown, the standout quotes? Sketch the sections first. 2. Add sections. dembrane drafts each from the conversations, in participants' own words. 3. Review against the sources. Use the library and chat to sanity-check nothing's missing. 4. Order it so the report reads top to bottom for your audience. > [!TIP] > Generate the [library](./library-and-analysis.md) first. It gives you the map of themes and > the best quotes, so you know which sections are worth having before you draft. Reports also include a *timeline* view - useful for a programme across several events or weeks, to see how the conversation evolved, not just its final shape. And a report isn't frozen: as more conversations come in, or after you improve the project's [context](./creating-a-project.md), regenerate the sections to refresh it. ## Share and send Two ways to get a report out: - *Publish* - make it available to share (owners, admins and members can publish; external collaborators cannot). - *Export* - download it, usually as a PDF for circulation. You can also put a report on a *schedule* so dembrane regenerates and emails it on a cadence - handy for a weekly digest to a steering group. Best of all: participants who left an email at the end of their session can be notified automatically when the report is ready or updated. Turn on participant updates in the [portal editor](./portal-editor.md) and you've got built-in post-event follow-up, including for people who couldn't attend. > [!IMPORTANT] > A published report shares findings, not raw recordings. If a stakeholder needs the source > transcripts, use [export](../../features/export-and-data-portability.md) instead - and mind > the [data-ownership](../../features/data-ownership-and-compliance.md) implications of who sees > what. ## What your plan gives you Reports use built-in analysis to draft their sections, so generation needs Changemaker or above. | You're on | Reports | |---|---| | *Free* | Generation gated under free-tier limits. | | *Innovator* | Generation gated (no built-in analysis). | | *Changemaker* | Full report generation, on EU-hosted Gemini. | | *Guardian* | As Changemaker, on an EU-sovereign stack (*coming soon*). | Publishing is also role-gated: external collaborators can generate but not publish. See the [capability matrix](../../features/roles-and-permissions.md). ## Related - [Reports - feature reference](../../features/reports.md) - the canonical how-it-works page. - [Export & data portability](../../features/export-and-data-portability.md) - transcripts, CSV/Excel, and transcript zips when you need the raw inputs. - [Library & analysis](./library-and-analysis.md) - find the themes and quotes before you draft. - [Chat & Ask](./chat-and-ask.md) - pull together what people said about one topic, with sources. - [Tiers, billing & usage](./tiers-billing-and-usage.md) - what each plan unlocks. --- # Managing your workspace (for hosts) A workspace holds your [projects](../../features/projects.md), conversations and people. If you're the owner or an admin, you run it: who's in, what they can do, who can see what. This is the quick how-to for those controls. Members can create and edit projects but not invite people or change settings; if you can't see the controls below, you're probably a member or collaborator. The full breakdown is in [roles & permissions](../../features/roles-and-permissions.md). ## Add and manage people Open your workspace and go to *Settings → Members*. From here you add people, set roles, and remove them. To invite, by *email* or *link*, pick a role: | You want them to… | Give them | |---|---| | Co-run the workspace with you | *admin* | | Create and edit projects - the everyday role | *member* | | See usage, invoices and payment, nothing else | *billing* | | Collaborate from outside (edit, chat, build reports) but not create/delete projects, invite or publish | *external* | | Only view, free and read-only ([external-client](../../features/partner-program.md) workspaces only) | *observer* | Email invites expire after *7 days*; link invites are the alternative when email is awkward. Pending invites and any access requests show up in the members area to approve or chase. > [!IMPORTANT] > You can't grant a role above your own. An admin can invite members and admins, but only an > owner can hand out owner-level access. To change a role, adjust it in the members list; remove people when they leave. One quirk: there's no "convert external to member" button. To promote an external collaborator, remove the external entry, add them to the organisation, and re-invite as a member - deliberate, because it crosses the org boundary. See [invites & access](../../features/invites-and-access.md). Most roles take a *seat* (owner, admin, member, billing, external); observer is free. Seats are metered, never blocked - inviting never hits a wall, the count just shows in your [usage](./tiers-billing-and-usage.md). A person counts once per workspace, pooled across a billing account. ## Set who can see the workspace Visibility controls who in your organisation can discover and join. Three states: - *Open to organisation* - everyone in the org sees it; org admins auto-join. Free at every tier, and the default. - *Invite-only* - invited people plus org admins. - *Private* - invited people only; org admins do not auto-join (the org owner can still carve in). The only paywalled move is leaving *open to organisation* - making a workspace more private needs Innovator or above. See [visibility & discovery](../../features/visibility-and-discovery.md). > [!TIP] > Start open if your team trusts each other - least friction. Tighten only when a workspace > genuinely needs walling off. ## Internal or external-client In *Settings → Data ownership*, set whether this is an *internal* workspace (shares the org's pooled billing, inherits org branding) or an *external-client* one (names a separate data owner, bills on its own, allows free observers, supports white-labelling). External-client is the [partner](../../features/partner-program.md) setup - read [data ownership & compliance](../../features/data-ownership-and-compliance.md) if you run work for outside clients. For an ordinary team workspace, leave it internal. ## Give the assistant standing context *[dembrane next only](../../features/dembrane-next.md).* If your team uses [Ask](./chat-and-ask.md#more-than-analysis), the workspace *General* settings carry two things for it: - *Assistant context* - guidance you write once that reaches every project chat in the workspace (*"We're a research agency; reports go to municipal clients, keep summaries formal and in Dutch"*). Admins edit it; it saves as you leave the field. - *Assistant memory* - notes the assistant saved about the workspace from people's chats. Anyone in the workspace shares them; *Remove* makes it forget one. The assistant writes these; people can only view and remove them. Project-level guidance stays on the project: its *context* field and an *Assistant memory* section in project settings work the same way, one project at a time. ## Staff support access If you hit a problem that is faster to troubleshoot from inside your workspace, you can temporarily grant dembrane staff admin-level support access. Access is fully controlled by you, off by default, and automatically expires after 24 hours. See [Staff support access](../../features/staff-support-access.md) for how to turn it on, approve incoming requests, and view access history. ## Other settings The rest of *Settings* is everyday setup: *name & logo* (per-workspace white-labelling is external-client only), *billing & usage* (your plan, seats, recording hours, invoices), and *inherit organisation branding* for internal workspaces. If you run several workspaces, the *organisation* around them is managed from org settings - members-by-workspace, access requests, pending invites, and an org-wide usage rollup. Org membership is independent of any single workspace. ## Related - [Staff support access](../../features/staff-support-access.md) - grant temporary, secure support access to your workspace. - [Roles & permissions](../../features/roles-and-permissions.md) - every role and exactly what it can do. - [Invites & access](../../features/invites-and-access.md) - adding people by email or link, and access requests. - [Visibility & discovery](../../features/visibility-and-discovery.md) - open, invite-only, or private. - [Organisations & workspaces](../../features/organisations-and-workspaces.md) - the containers and how they nest. - [Data ownership & compliance](../../features/data-ownership-and-compliance.md) - internal vs external, and who owns what. - [Tiers, billing & usage](./tiers-billing-and-usage.md) - seats, plans, and what's gated. --- # Tiers, billing & usage (for hosts) dembrane comes in four plans - *Free, Innovator, Changemaker, Guardian*. Your workspace's plan decides your recording hours, whether you get built-in [analysis](./library-and-analysis.md) and [reports](./reports.md), and a few compliance features on top. Here's what each gives you, how seats and usage work, and how to move up. The full breakdown is in the canonical [tiers & billing](../../features/tiers-and-billing.md) reference. ## The plans Each tier includes everything below it, and each is counted in seats. There's no published price: contact dembrane for current pricing. See [upgrading](#upgrading). | Capability | Free | Innovator | Changemaker | Guardian | |---|---|---|---|---| | Secure transcription | ✓ | ✓ | ✓ | ✓ | | Recording hours | 1 h | unlimited | unlimited | unlimited | | Bring-your-own-LLM + MCP | - | ✓ | ✓ | ✓ | | Built-in analysis (Gemini) | - | - | ✓ | ✓ | | Audit logs | - | - | ✓ | ✓ | | White-labelling | - | - | ✓ | ✓ | | EU-sovereign stack | - | - | - | ✓ | In practice: - *Free* - 1 hour of recording, a single user, secure transcription. The only tier with an hours cap. Good for trying dembrane on a small session. - *Innovator* - unlimited hours, *no built-in analysis*; the [chat screen](./chat-and-ask.md) becomes a bring-your-own-LLM integration over MCP (connect ChatGPT/Claude). *Coming soon*, gated on MCP shipping. - *Changemaker* - unlimited hours plus *built-in analysis* on EU-hosted Gemini ([library](./library-and-analysis.md), [reports](./reports.md), chat), audit logs, and white-labelling. Available now. - *Guardian* - everything in Changemaker on a CLOUD-Act-safe EU-sovereign stack. *Coming soon*. > [!NOTE] > Existing paying customers move to Changemaker (unlimited hours) until renewal. Bespoke > compliance and self-hosting are available - talk to dembrane. ## Seats Most roles take a *seat*: owner, admin, member, billing, external. *Observer* is free. Seats are metered, never blocked - inviting never hits a wall, the count just shows in usage. A person counts once per workspace, pooled across the workspaces on a billing account. See [roles & permissions](../../features/roles-and-permissions.md) for which role does what, and [managing your workspace](./managing-your-workspace.md) for adding people. ## Usage Open *Settings → Billing & usage* (or the org-wide rollup if you run several workspaces) to see your *recording hours* (capped at 1 h on Free, unlimited above), *seats* in use, and per-project usage under each project's own *Usage* section. > [!TIP] > On Free, if you're planning a session over an hour, check usage and upgrade before the event, > not mid-recording. On paid tiers, hours are unlimited. ## Upgrading Use the in-app contact flow or contact dembrane to discuss an upgrade. If you don't hold billing access, you can also *request an upgrade* from inside the workspace. It goes to whoever can approve it (your workspace owner or admin, or dembrane staff for free-tier requests), and you're notified of the decision. If your workspace already pays, none of this changes it. Your plan, your amount and your invoices stay under *Settings → Billing & usage*, and you manage the subscription there as before. ## What's gated, at a glance | If you're blocked from… | You need… | |---|---| | Recording past 1 hour | Innovator or above | | The library, reports, dembrane's built-in chat | Changemaker or above | | Audit logs, white-labelling | Changemaker or above | | Making a workspace/project more private than "open" | Innovator or above | | An EU-sovereign stack | Guardian (*coming soon*) | ## Related - [Tiers & billing - feature reference](../../features/tiers-and-billing.md) - the canonical plan page, and how to get a price. - [Roles & permissions](../../features/roles-and-permissions.md) - which roles take seats and what they can do. - [Managing your workspace](./managing-your-workspace.md) - adding people and reading usage. - [Library & analysis](./library-and-analysis.md) and [reports](./reports.md) - the headline Changemaker features. - [Chat & Ask](./chat-and-ask.md) - built-in on Changemaker, bring-your-own-LLM on Innovator. --- # Account & settings (for hosts) This page is about *you*, not the work: the personal settings that follow you around whichever workspace you're in. They're yours regardless of your [role](../../features/roles-and-permissions.md). Open *Settings* from the dashboard to find them. (The one exception is audit logs, a Changemaker-and-above feature - see below.) The full reference is [account & security](../../features/account-and-security.md). ## Profile and password Set your *display name* under your profile - it's what colleagues see in member lists, invites and activity. Change your password from *Account & security*; if you've forgotten it, use the *reset password* flow on the sign-in screen to get an emailed link without needing the old one. ## Two-factor authentication Turn on *2FA* from *Account & security* for a second step at sign-in. It's the single biggest thing you can do to protect your account. > [!TIP] > If your work involves personal or sensitive recordings, switch on 2FA before you start > collecting. It protects the people who trusted you with their words as much as it protects you. ## Appearance and language Under *Appearance*, set the dashboard interface to one of *eight languages* (English, Dutch, German, French, Spanish, Italian, Ukrainian, Czech) and adjust *font* and *text size* for comfort. These are display preferences only - they don't change your projects or who sees them. Transcription is multilingual whatever your interface language; see [transcription](../../features/transcription.md). ## My access *My access* lists every organisation and workspace you belong to, and your role in each - the quickest way to answer *"why can't I see that project?"*. Your role decides what you can do (see the [capability matrix](../../features/roles-and-permissions.md)); if something's missing, you may need an [invite or to request access](../../features/invites-and-access.md). Note that org and workspace membership are separate - you can be in an org with no workspaces, or in a single workspace with no org membership, and My access shows both. ## Project defaults You can set *project defaults* such as the *legal basis* used for new projects - set it once to save repeating yourself and keep projects consistent for compliance. See [data ownership & compliance](../../features/data-ownership-and-compliance.md). ## Assistant *[dembrane next only](../../features/dembrane-next.md).* If you use [Ask](./chat-and-ask.md#more-than-analysis), the assistant can save notes about how you like to work. The *Assistant* section shows everything it remembers about you - only you see these notes - and *Remove* makes it forget one for good. It writes the notes during your chats; you can't edit them here, only remove them. ## Audit logs *Audit logs* record who did what, and when - useful for accountability on a sensitive engagement, or tracing a change nobody remembers making. > [!IMPORTANT] > Audit logs are *Changemaker* and above. On Free and Innovator they aren't available. See > [tiers, billing & usage](./tiers-billing-and-usage.md). ## Deleting your account To comply with App Store and privacy guidelines, you can delete your account directly in the dembrane Go mobile app. Before you do, check what it means for any projects you own and for [data ownership](../../features/data-ownership-and-compliance.md). Make sure to hand over or move work others rely on before proceeding. When you initiate account deletion: - Your account is suspended immediately, which blocks logins and token refreshes. - This marks the account for permanent removal, which is processed out-of-band by dembrane administrators within 30 days. ## Related - [Account & security - feature reference](../../features/account-and-security.md) - the canonical page on profile, password, 2FA, and audit logs. - [Roles & permissions](../../features/roles-and-permissions.md) - what your role in each workspace lets you do. - [Invites & access](../../features/invites-and-access.md) - getting access to a workspace or project you're missing. - [Managing your workspace](./managing-your-workspace.md) - if you also run a workspace. - [Tiers, billing & usage](./tiers-billing-and-usage.md) - audit logs and what else each plan unlocks. --- # The SMART loop > [!IMPORTANT] > The living canvas at the heart of this story is now in *beta* on > [dembrane next](../features/dembrane-next.md). It's off by default for every project: a > host opts a project in with the *Living canvas* switch (marked *Beta*) under > *Experimental* on the General page of project settings. With the switch off there are no > canvas pages, no canvas abilities in chat, and no background regeneration. The canvas is > not in production yet; making it production-ready is a separate, upcoming effort. The > rest of this story is still being built. It's published so you can see what's coming and > tell us early if it misses your reality. The idea in one line: your sessions produce living artifacts, and those artifacts feed back into the session while it's still running. The story below is the acceptance test - the feature is done when this works end to end. ## The story: the live panel wall Marieke runs public participation for a municipality. Tomorrow: a day-long citizen panel on the new mobility plan - 8 tables, each recording via the portal QR, 10:00 to 17:00. ### The evening before: creating the project is a conversation Marieke creates the project - and lands directly in a chat: > *"Welcome to your project. I'll help you set it up - start by describing what you're > planning, in your own words. (You can also skip this and come back any time, or read the > [docs](../users/host/creating-a-project.md) and set things up yourself.)"* This is the project's *methodology* at work. Every project starts on the default *dembrane methodology*: figure out what this project is for, and shape everything around that. If Marieke (or her workspace) already has methodologies of her own, they're offered right here - *"Start from Panel day v3, or shall we figure this one out from scratch?"* - so a way of working she's refined before is one tap away. The assistant interviews her - a few short questions, each with concrete options to pick from - and together they land on the project's *goal*: surface concerns and suggestions per neighbourhood; final report structured by theme, formal Dutch. The goal is saved, versioned, and steers every report and artifact from here on. Because she mentioned the event, the assistant asks one more thing: > *"Your panel runs tomorrow 10:00-17:00. Would you like to let the dembrane team know? When > they know an event is coming they can keep an eye on things from their side."* She says yes; a heads-up goes into the team's queue with the event time. Nothing is ever sent without asking her first. ### Morning: asking for something alive > *"All 8 tables are recording until 5pm. I want a live overview on the big screen in the > hall - themes as they emerge, a counter of voices heard, a fresh quote or two. Keep it > updated through the day."* The assistant proposes a *loop* - a card she reviews before anything runs: > **Live panel wall** - stays up to date through the day, until *today 17:00* · pauses > itself when nothing new arrives. She applies it. The wall keeps itself fresh - every few minutes, quietly - and its design only changes when she asks. Every loop has an end: the assistant always sets one and says it out loud. Later she can say *"pause the wall"* in the same chat. ### The wall appears The first run builds it: a *dynamic canvas* - theme tiles, a chart, a rotating quote, a live corner showing who's recording - freshly generated by the assistant every few minutes, in dembrane's look. It works through Marieke's own access: exactly the 8 tables she can see, nothing more. *Live panel wall* appears in the project sidebar, alongside her reports - same familiar shape: open it, watch it stay current, view it full screen on the venue display. ### Every change is kept The wall has two kinds of change, and both are kept. Fresh *data* flows in every few minutes without anyone doing anything - those snapshots let Marieke step back through the day (the wall at 10:20 with two shy themes, the wall at 14:00 with six) and see how the conversation evolved. Changes to the wall *itself* - its design, what it shows - only happen when she asks, and each one is a new *version*, kept forever. Nothing is ever overwritten. ### Feedback is just chat The wall's quotes are too small from the back of the hall. Marieke opens the wall on her laptop and, on her phone, tells the chat: > *"Bigger quotes, drop the counter."* The next version reflects it. The assistant coaches this gently the first time - *"you can ask me to change anything about this wall; each change becomes a new version"* - because talking to your artifact is new, and it should feel obvious within one exchange. ### Asking for something that doesn't exist yet > *"Can each theme tile have a generated image? Something visual for the hall."* The assistant checks what it can actually do (this documentation is its ground truth) and doesn't bluff: > *"Generated images aren't something I can put in an artifact today. Can I ask two quick > questions so the team hears exactly what you need?"* Two questions with options - what job the image does, what would work instead - and then, with her go-ahead, a detailed request goes to the dembrane team, carrying enough context to reach her back. Meanwhile the wall gets bold colour-coded tiles: the best version of what *is* possible today. ### The loop feeds the room At 11:40 the wall surfaces a theme she didn't expect - *bus route 12*. Before walking over, she taps *refresh now* on the wall to catch the very latest, then asks two tables to dig into it. The next refresh shows the theme growing. That moment - the artifact changing what happens in the session - is the whole point of the loop. Over lunch, runs report "nothing new" and skip the rebuild. ### It ends cleanly At 17:00 the loop expires: one final version, marked final, the chat thread holding the day's run history. *"Turn today's wall into the closing report"* - and the report builder takes over, seeded by the goal and the artifact. ### The day after: the way of working becomes reusable Reading the closing report, the assistant notices the shape of what Marieke did - setup interview, live wall during the session, themes probed in the room, closing report by neighbourhood - and suggests: > *"This worked. Want me to extract it as a methodology? Next panel, you'd start from this > instead of from scratch."* She says yes. The assistant writes up *Panel day* - the reasoning behind the decisions, the goal template, the wall recipe, the report structure - as a methodology: versioned, hers to edit, selectable when she creates her next project. Over time her team refines it; version by version, it becomes how her municipality runs panels. ### Weeks later A message lands in the same chat: *"Theme images shipped - your wall can use them next session."* The request she made in the hall came back as a feature, to her, in the place she asked for it. And quietly, the canvas-maker itself got better. What Marieke asked for - and what hundreds of other hosts asked their canvases for - taught the assistant's canvas-building craft new moves. Her next wall starts from everything everyone learned. ## What this needs (in plain terms) - *Project creation as a conversation*: a new project opens straight into its setup chat, with honest escape hatches (skip, come back later, read the docs). - *Methodologies*: the way a project is run, as a thing you can name, version, select, and improve - starting with the default *dembrane* methodology, extracted from real projects when the assistant notices something worked, edited by you, and one day shared and published with evidence attached. - *Loops*: recurring assistant runs with a cadence, a hard expiry, and a lifecycle you manage by chatting - propose, apply, pause, resume, stop. Every part of an artifact is a question being answered on a rhythm: *"what are people talking about right now?"*, *"what are the themes?"*, *"how is the mood shifting?"* - one answer every few minutes, each with its own pace, full history kept. Marieke's wall tracks themes and a what's-happening line side by side, and she adds or rephrases the questions by chatting. The one truly-live element is the monitor - dembrane's existing real-time view - which can sit inside an artifact as a widget. You never have to think about any of this machinery. - *Try before apply*: every change to an artifact shows you a preview right in the chat - with your real data when you have some, with clearly-marked sample data when you don't - and nothing goes live until you apply it. For a full rehearsal, the assistant will walk you through a two-minute test recording you can delete afterwards. - *The dynamic canvas*: a living page the assistant generates for you and keeps fresh - charts, tiles, anything a page can show, in dembrane's look - with a *refresh now* button for the impatient moment. (Later: compose several frames, plain answers, and the live monitor side by side.) The page runs in a locked frame with no access to anything; the generation itself acts with your reading access and nothing more. - *A craft that compounds*: the assistant's canvas-building know-how is one shared, versioned skill - improved over time by what hosts everywhere ask for. Requests that can't be met yet become the interviews and insights that teach it. - *Artifacts*: report-shaped things that aren't reports - versioned forever, regenerated in place. - *Feedback by chat*: an artifact is something you talk to; every change is a new version. - *Honest gaps*: when you ask for something that doesn't exist, a short interview captures what you actually need, and - with your consent - the team hears it and can reach you back when it ships. ## Related - [Building now](./index.md) - everything else in progress. - [Chat & Ask](../features/chat-and-ask.md) - the assistant this builds on. - [Reports](../features/reports.md) - the shape artifacts borrow. - [dembrane next](../features/dembrane-next.md) - where the canvas beta is live today. --- # dembrane documentatie dembrane helpt groepen om wat mensen *zeggen* om te zetten in iets waar ze *naar kunnen handelen*. Mensen praten - in een werksessie, een inspraakavond, een burgerpanel, een onderzoeksinterview - en dembrane neemt het op, transcribeert het veilig in tientallen talen, en zet uren aan dialoog om in samenvattingen, thema's, rapporten en een chat waar je vragen aan kunt stellen. We bouwen op één overtuiging: *mensen weten hoe.* Gemeenschappen bezitten de kennis al om hun eigen uitdagingen op te lossen. dembrane voegt geen intelligentie toe aan een groep - het brengt de intelligentie naar boven die er al is, en houdt de mensen in de kamer stevig aan het roer. dembrane heette vroeger ECHO. Die oude naam duikt hier en daar nog op, in bestandspaden, image-namen en ouder materiaal. > [!NOTE] > Nieuw hier? De snelste route is de *[Snelstart voor hosts](./users/host/getting-started.md)*. > Alleen hier om op te nemen op uitnodiging? Zie *[voor deelnemers](./users/participant/index.md)*. > [!IMPORTANT] > De Nederlandse vertaling is in uitvoering. Deze welkomstpagina is alvast vertaald om de > taalwisselaar te testen; de meeste onderliggende pagina's openen voorlopig nog in het > Engels. Gebruik de *EN / NL*-schakelaar rechtsboven om van taal te wisselen. ## Vind je weg Kies de gids die past bij wat je doet: - *[Ik leid sessies en analyseer ze - Host](./users/host/index.md)* Projecten maken, gesprekken verzamelen, transcripten lezen, met je data chatten, rapporten bouwen. - *[Ik host werk voor externe klanten - Partner](./users/host-partner/index.md)* Werkruimtes voor externe klanten, de gratis observer-rol, data-eigenaarschap en overdracht. - *[Ik werk bij dembrane - Staff](./users/staff/index.md)* Facturatie, accountgezondheid, upgrade-verzoeken, partnerbeheer en trainingen. - *[Iemand nodigde me uit om op te nemen - Deelnemer](./users/participant/index.md)* Wat je kunt verwachten, hoe je opneemt, en wat er met je woorden gebeurt. - *[Ik bouw op dembrane - Ontwikkelaar](./users/developer-external/index.md)* Zelf hosten, de API, webhooks, configuratie, licentie en bijdragen. - *[Ik werk aan de dembrane-codebase - Interne ontwikkelaar](./users/developer-internal/index.md)* Architectuur, het datamodel, de verwerkingspijplijn, en hoe het wordt uitgerold. ## Blader per functie Wil je liever vanuit een mogelijkheid starten dan vanuit een persoon? De *[functiecatalogus](./features/index.md)* documenteert elk onderdeel van dembrane op eigen voorwaarden - wat het is, wanneer je het zou gebruiken, en voor wie het is. ## De hele kaart De *[documentatiekaart](./map.md)* toont elke pagina op één plek. --- # Problemen met transcripten & samenvattingen oplossen dembrane zet gesproken woorden om in tekst en duidelijke, beknopte samenvattingen. Meestal gebeurt dit binnen een minuut nadat de opname is beëindigd. Als jouw transcript slordig is, de samenvatting niet klopt of je je afvraagt waarom een gesprek leeg blijft, volg dan deze stappen om het op te lossen. ## 1. Het transcript bevat fouten of is moeilijk te lezen De kwaliteit van de transcriptie hangt sterk af van de helderheid van het geluid en de context van de gebruikte woorden. Als eigennamen, namen van personen of vakjargon verkeerd gespeld of verkeerd verstaan worden: ### Stap 1: Controleer en update de Sleuteltermen van jouw project Het meest effectieve hulpmiddel voor betere transcripties is de lijst met *Sleuteltermen* in de project- of portaalinstellingen. - Navigeer naar jouw projectinstellingen of de portaaleditor. - Voeg de eigennamen, namen van deelnemers, projectafkortingen en vaktermen (zoals specifieke softwarenamen, lokale plaatsen of technisch jargon) toe die mensen waarschijnlijk zullen noemen. - *Tip: Als je een sessie organiseert over een specifiek onderwerp, vul deze termen dan al in voordat mensen beginnen te spreken.* ### Stap 2: Transcribeer het gesprek opnieuw Zodra jouw lijst met Sleuteltermen is bijgewerkt, kun je de audio opnieuw verwerken om een beter transcript te genereren: - Open het gesprek in jouw dashboard. - Klik op de knop *Opnieuw transcriberen* (het vernieuwingspictogram naast de titel van het transcript). - Bevestig de instellingen in de pop-up en start de her-transcriptie. - *Dit creëert een nieuw, gecorrigeerd gesprek met de verbeterde transcriptie, terwijl de originele opname intact blijft.* --- ## 2. De samenvatting is onnauwkeurig, verouderd of te algemeen Samenvattingen worden gegenereerd door taalmodellen die de getranscribeerde tekst analyseren. Als een samenvatting niet nuttig is, komt dat meestal doordat het onderliggende transcript onnauwkeurig was of omdat het taalmodel meer sturing nodig had over wat prioriteit moet krijgen. ### Stap 1: Zorg dat het transcript klopt Als de transcriptie slordig was, volg dan de stappen hierboven om het gesprek *opnieuw te transcriberen* met de juiste Sleuteltermen. Een samenvatting kan immers pas nauwkeurig zijn als de tekst die wordt samengevat dat ook is. ### Stap 2: Definieer het doel en de methodologie van jouw project Het taalmodel gebruikt het *Doel* en de *Methodologie* van jouw project om te bepalen waar het naar moet zoeken en wat de nadruk moet krijgen in de samenvattingen. - Controleer het overzicht of de instellingen van jouw project om te zorgen dat het Doel duidelijk is. - Pas het Doel aan als je wilt dat de samenvatting zich richt op specifieke thema's of vragen. ### Stap 3: Genereer de samenvatting opnieuw Als je het transcript hebt gecorrigeerd of de projectdoelen hebt aangepast, kun je een frisse samenvatting opvragen: - Open het gesprek in jouw dashboard. - Klik naast de kop *Samenvatting* op de knop *Opnieuw genereren* (het herstart-/vernieuwingspictogram). - Bevestig de herberekening. Het taalmodel gooit de oude samenvatting weg en schrijft een frisse samenvatting op basis van het huidige transcript en de projectcontext. --- ## 3. Het transcript of de samenvatting is leeg Als er een gesprek in jouw dashboard verschijnt maar er is geen tekst of samenvatting, raak dan niet in paniek. Controleer deze veelvoorkomende situaties: - *Geef het een minuutje:* Een gesprek verschijnt direct nadat de opname is beëindigd, maar de transcriptie en het genereren van de samenvatting duren meestal tussen de *30 seconden en een minuut*. Ververs de pagina na een korte wachttijd. - *Controleer het label "Leeg":* Als het gesprek is gemarkeerd met het label "Leeg", betekent dit dat er geen spraak is gedetecteerd in het audiobestand (bijvoorbeeld als een deelnemer per ongeluk een stille opname heeft ingestuurd of microfoonproblemen had). - *De verwerking loopt vast:* Als er enkele minuten zijn verstreken en het gesprek nog steeds aan het laden is of geen transcript heeft, is er mogelijk een deel van de verwerking mislukt. Je kunt gerust proberen het gesprek *opnieuw te transcriberen* om het proces te herstarten, of mailen naar *support@dembrane.com* als het probleem aanhoudt. ## Gerelateerd - [Transcripten & gesprekken](./transcripts-and-conversations.nl-NL.md) - [Gesprekken verzamelen](./collecting-conversations.nl-NL.md) - [Het portaal instellen](./portal-editor.nl-NL.md)