Architecture Decisions
This section captures architectural decisions made on Open Chat Studio as Architecture Decision Records (ADRs). See ADR-0000 for why this exists.
See the ADR process developer guide for the step-by-step instructions to create an ADR by hand or manually extract ADRs with AI agent.
Index
| ADR | Status | Title |
|---|---|---|
| 0000 | ACCEPTED | Record architecture decisions |
| 0001 | ACCEPTED | Use AWS SES + django-anymail signal handler for email ingress |
| 0002 | ACCEPTED | Slack-style routing priority chain for email channel |
| 0003 | ACCEPTED | Email thread continuity via ExperimentSession.external_id |
| 0004 | ACCEPTED | Persist inbound email attachments in the webhook handler |
| 0005 | ACCEPTED | Validate inbound email attachments by content sniffing |
| 0006 | ACCEPTED | Combine email reply text and attachments into a single message |
| 0007 | ACCEPTED | Adopt ty as the Python type checker |
| 0008 | ACCEPTED | Enable ty rules progressively from a baseline of all-ignored |
| 0009 | ACCEPTED | Context-based stateless message processing pipeline |
| 0010 | ACCEPTED | Exception-based early exit with guaranteed terminal stages |
| 0011 | ACCEPTED | Silent pipeline halt via EarlyAbort |
| 0012 | ACCEPTED | Lean Score value layer in apps/assessments |
| 0013 | ACCEPTED | Dual-write Scores from evaluations and annotations |
| 0014 | ACCEPTED | Minimal read-side concordance view backed by Score |
| 0015 | ACCEPTED | Dedicated human_annotations app with queue/item/annotation/aggregate model |
| 0016 | ACCEPTED | Authoritative annotation for multi-reviewer consensus |
| 0017 | ACCEPTED | Eager per-submission aggregation into a per-queue record |
| 0018 | ACCEPTED | Scope team querysets by FK identity, not slug join |
| 0019 | ACCEPTED | Poll source experiments to auto-populate evaluation datasets |
| 0020 | ACCEPTED | Delta evaluation runs scoped to newly appended messages |
| 0021 | ACCEPTED | Invest in API surface, not a read-only role |
| 0022 | ACCEPTED | URL-path API versioning, v1 frozen / v2 new |
| 0023 | ACCEPTED | Rename experiment to chatbot in the v2 API |
| 0024 | ACCEPTED | inspect as a denormalized read-only projection |
| 0025 | ACCEPTED | Inline nested resource tree for the inspect payload |
| 0026 | ACCEPTED | Identify v2-exposed resources by database primary key |
| 0027 | ACCEPTED | Secrets exclusion via per-resource allowlist serializers |
| 0028 | ACCEPTED | Inspect authorizes on chatbot view + team scope, not per-resource permissions |
| 0029 | ACCEPTED | Download WhatsApp inbound attachments in an overridden hydration stage |
| 0030 | ACCEPTED | Gate the email channel with a global allowed-domains setting |
| 0031 | ACCEPTED | Collection content is a live shared resource |
| 0032 | ACCEPTED | Validate Jinja templates server-side by parsing the AST |
| 0033 | ACCEPTED | Structured runtime Jinja error messages |
| 0034 | ACCEPTED | Tiered feature deprecation gated by a usage audit |
| 0035 | ACCEPTED | Read-only mode gates features during the deprecation window |
| 0036 | ACCEPTED | Sunset headers and 410 Gone for retired HTTP surfaces |
| 0037 | ACCEPTED | Row-multiplying list filters use EXISTS, not a blanket DISTINCT |
| 0038 | ACCEPTED | Redirect version snapshot URLs to the working version |
| 0039 | ACCEPTED | Require proof of possession for chat session access |
| 0040 | ACCEPTED | Stateless signed session tokens with server-side inactivity expiry |
| 0041 | ACCEPTED | Fail-closed session-token enforcement rollout |
| 0042 | ACCEPTED | Settings-driven internal team metadata in a JSON field |
| 0043 | ACCEPTED | BSUID participant identity for WhatsApp |
| 0044 | ACCEPTED | Durable per-channel widget auth policy |
| 0045 | ACCEPTED | Ratchet widget auth level up on upgrade |
| 0046 | ACCEPTED | Node rows are the sole source of pipeline node content |
| 0047 | ACCEPTED | Deploy-safe evaluation runs via a beat coordinator over a frozen plan |
| 0048 | ACCEPTED | Evaluation spend is team spend, never entity spend |
| 0049 | ACCEPTED | Node rows own pipeline layout; Pipeline.data keeps only edges |
| 0050 | ACCEPTED | Eval-driven generation is evaluation spend, billed without a trace |
| 0051 | ACCEPTED | One set of activity-metric definitions across usage surfaces |
| 0052 | ACCEPTED | App-layer rate limiting via an in-house fixed-window core |
| 0053 | ACCEPTED | Starting a chat session requires team membership or the embed key |