Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
4aeb60e
feat: initialize monorepo structure and development infrastructure
github-actions[bot] Apr 10, 2026
b058198
chore: remove ci.yml from commit (GitHub App lacks workflows permission)
github-actions[bot] Apr 10, 2026
9c37e3c
Merge pull request #18 from deepducks/claude/issue-1-20260410-2122
ggondim Apr 10, 2026
7346892
feat(core): implement data model types, storage & channel adapter int…
github-actions[bot] Apr 10, 2026
3859e35
Merge meta/17 into claude/issue-2, keeping issue-2 versions for confl…
ggondim Apr 10, 2026
fd7887b
Merge pull request #19 from deepducks/claude/issue-2-20260410-2134
ggondim Apr 10, 2026
77fb35f
feat(core): implement token, thread, and turn management
github-actions[bot] Apr 10, 2026
cbd4f23
feat(core): implement router matching engine (#3)
github-actions[bot] Apr 10, 2026
71e1c3f
Merge meta/17: combine issue #2 types with issue #5 managers
ggondim Apr 10, 2026
cf32514
Merge pull request #20 from deepducks/claude/issue-5-20260410-2150
ggondim Apr 10, 2026
494d7c3
Merge meta/17 into issue-3 branch
ggondim Apr 10, 2026
cd8ee0b
Merge pull request #21 from deepducks/claude/issue-3-20260410-2149
ggondim Apr 10, 2026
020568f
feat: implement MongoDB StorageAdapter (issue #6)
github-actions[bot] Apr 10, 2026
177b048
Merge meta/17 into issue-6 branch
ggondim Apr 10, 2026
febfe15
Merge pull request #22 from deepducks/claude/issue-6-20260410-2149
ggondim Apr 10, 2026
03f20a8
feat: implement Slack channel adapter (#7)
github-actions[bot] Apr 10, 2026
c72911f
Merge meta/17 into issue-7 branch
ggondim Apr 10, 2026
34fa699
Merge pull request #23 from deepducks/claude/issue-7-20260410-2150
ggondim Apr 10, 2026
ccf2245
feat: implement Discord channel adapter
github-actions[bot] Apr 10, 2026
3ffa2d3
feat: implement Core Reply Engine (#4)
github-actions[bot] Apr 10, 2026
b78e796
feat(channels): add WhatsApp adapter via Baileys (issue #10)
github-actions[bot] Apr 10, 2026
ed77103
Merge meta/17 into issue-4 branch
ggondim Apr 10, 2026
b468469
Merge pull request #24 from deepducks/claude/issue-4-20260410-2207
ggondim Apr 10, 2026
70d8dd7
feat: implement Telegram channel adapter
github-actions[bot] Apr 10, 2026
133da3e
feat(server): implement API routes, auth, and infrastructure
github-actions[bot] Apr 10, 2026
198bd75
Merge pull request #26 from deepducks/claude/issue-9-20260410-2205
ggondim Apr 10, 2026
09e060f
Merge pull request #27 from deepducks/claude/issue-10-20260410-2206
ggondim Apr 10, 2026
44241db
Merge pull request #28 from deepducks/claude/17-issue-11-20260410-2220
ggondim Apr 10, 2026
da8401b
Merge meta/17 into issue-8
ggondim Apr 10, 2026
b3ecfc1
Merge pull request #25 from deepducks/claude/issue-8-20260410-2205
ggondim Apr 10, 2026
b57fda6
feat(server): implement auto-generated A2H forms (methods 3 & 4)
github-actions[bot] Apr 10, 2026
a347679
Merge pull request #29 from deepducks/claude/17-issue-12-20260410-2321
github-actions[bot] Apr 10, 2026
4096dfd
feat(server): build management dashboard UI
github-actions[bot] Apr 10, 2026
7089699
Merge meta/17 to resolve conflicts
ggondim Apr 10, 2026
361af4b
Merge pull request #30 from deepducks/claude/17-issue-13-20260410-2321
ggondim Apr 10, 2026
476a6d9
feat(trust): implement optional trust layer — JWS, auth, audit, repla…
github-actions[bot] Apr 10, 2026
38cf35b
Merge pull request #31 from deepducks/claude/17-issue-14-20260410-2337
github-actions[bot] Apr 10, 2026
1e9f0c5
feat(#15): integration testing and hardening
github-actions[bot] Apr 10, 2026
30a1ec9
Merge pull request #32 from deepducks/claude/17-issue-15-20260410-2337
github-actions[bot] Apr 10, 2026
3cb8b40
feat: release & developer experience (issue #16)
github-actions[bot] Apr 11, 2026
a02e2a3
Merge pull request #33 from deepducks/claude/17-issue-16-20260410-2355
github-actions[bot] Apr 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# =============================================================================
# OpenThreads — Environment Variables
# Copy this file to .env and fill in your values.
# =============================================================================

# Server
PORT=3000
NODE_ENV=development

# Logging (structured JSON logging)
# LOG_LEVEL=info # debug | info | warn | error (default: info)
# LOG_FORMAT=text # json | text (default: json in production, text in development)

# MongoDB
# When using Docker Compose: mongodb://openthreads:openthreads@localhost:27017/openthreads
MONGODB_URI=mongodb://openthreads:openthreads@localhost:27017/openthreads

# Security
# IMPORTANT: Change this in production! Use a long, random string.
JWT_SECRET=change-me-in-production

# Management API Key — required to access /api/channels, /api/recipients, /api/routes
# Leave unset to allow unauthenticated access in development.
# MANAGEMENT_API_KEY=change-me-in-production

# Reply Token TTL (in seconds)
# Default: 86400 (24 hours)
REPLY_TOKEN_TTL=86400

# Base URL for OpenThreads (used to build replyTo URLs and form links)
OPENTHREADS_BASE_URL=http://localhost:3000

# =============================================================================
# Channel Credentials
# Add credentials for each channel you want to enable.
# =============================================================================

# Slack
# SLACK_BOT_TOKEN=xoxb-your-slack-bot-token
# SLACK_SIGNING_SECRET=your-slack-signing-secret
# SLACK_APP_TOKEN=xapp-your-slack-app-token

# Telegram
# TELEGRAM_BOT_TOKEN=your-telegram-bot-token

# Discord
# DISCORD_BOT_TOKEN=your-discord-bot-token
# DISCORD_CLIENT_ID=your-discord-client-id

# =============================================================================
# Trust Layer (optional)
# Enable for production deployments requiring strong authentication and
# cryptographic evidence (JWS signing, WebAuthn, audit logging).
# =============================================================================

# TRUST_LAYER_ENABLED=false
# TRUST_JWS_ALGORITHM=RS256
# TRUST_PRIVATE_KEY_PATH=./keys/private.pem
# TRUST_PUBLIC_KEY_PATH=./keys/public.pem

# =============================================================================
# Observability (optional)
# =============================================================================

# OpenTelemetry — set OTEL_EXPORTER_OTLP_ENDPOINT to enable tracing
# OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
# OTEL_SERVICE_NAME=openthreads
# OTEL_SDK_DISABLED=false
32 changes: 32 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Dependencies
node_modules/

# Build outputs
dist/
.next/
*.tsbuildinfo

# Environment files
.env
.env.local
.env.*.local
!.env.example

# IDE
.vscode/
.idea/
*.swp
*.swo
.DS_Store
Thumbs.db

# Logs
*.log
npm-debug.log*
bun-debug.log*

# Test coverage
coverage/

# OS
.DS_Store
6 changes: 6 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules/
dist/
.next/
coverage/
*.lockb
bun.lockb
9 changes: 9 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100,
"arrowParens": "always",
"endOfLine": "lf"
}
53 changes: 53 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# ─── Build stage ─────────────────────────────────────────────────────────────
FROM oven/bun:1.2 AS builder

WORKDIR /app

# Copy workspace manifests first for layer caching
COPY package.json bun.lockb* ./
COPY packages/core/package.json ./packages/core/
COPY packages/server/package.json ./packages/server/
COPY packages/storage/mongodb/package.json ./packages/storage/mongodb/
COPY packages/trust/package.json ./packages/trust/
COPY packages/channels/package.json ./packages/channels/
COPY packages/channels/discord/package.json ./packages/channels/discord/
COPY packages/channels/slack/package.json ./packages/channels/slack/
COPY packages/channels/telegram/package.json ./packages/channels/telegram/
COPY packages/channels/whatsapp/package.json ./packages/channels/whatsapp/

RUN bun install --frozen-lockfile

# Copy source
COPY tsconfig.base.json tsconfig.json ./
COPY packages ./packages

# Build the Next.js server
WORKDIR /app/packages/server
ENV NEXT_TELEMETRY_DISABLED=1
RUN bun run build

# ─── Production stage ─────────────────────────────────────────────────────────
FROM oven/bun:1.2-slim AS runner

WORKDIR /app

ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000

RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs

# Copy built artifacts
COPY --from=builder /app/packages/server/.next/standalone ./
COPY --from=builder /app/packages/server/.next/static ./packages/server/.next/static
COPY --from=builder /app/packages/server/public ./packages/server/public 2>/dev/null || true

USER nextjs

EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
CMD bun -e "fetch('http://localhost:3000/api/health').then(r=>r.ok?process.exit(0):process.exit(1)).catch(()=>process.exit(1))"

CMD ["bun", "packages/server/server.js"]
21 changes: 21 additions & 0 deletions deploy/helm/openthreads/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: v2
name: openthreads
description: >
OpenThreads — a unified messaging gateway with human-in-the-loop support.
Bridges Slack, Discord, Telegram, WhatsApp, and other channels to any
HTTP-based agent or service via the A2H protocol.
type: application
version: 0.1.0
appVersion: "0.1.0"
keywords:
- openthreads
- a2h
- human-in-the-loop
- messaging
- webhook
home: https://github.com/deepducks/OpenThreads
sources:
- https://github.com/deepducks/OpenThreads
maintainers:
- name: DeepDucks
url: https://github.com/deepducks
60 changes: 60 additions & 0 deletions deploy/helm/openthreads/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "openthreads.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
*/}}
{{- define "openthreads.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Create chart label.
*/}}
{{- define "openthreads.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels.
*/}}
{{- define "openthreads.labels" -}}
helm.sh/chart: {{ include "openthreads.chart" . }}
{{ include "openthreads.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels.
*/}}
{{- define "openthreads.selectorLabels" -}}
app.kubernetes.io/name: {{ include "openthreads.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
ServiceAccount name.
*/}}
{{- define "openthreads.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "openthreads.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
74 changes: 74 additions & 0 deletions deploy/helm/openthreads/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "openthreads.fullname" . }}
labels:
{{- include "openthreads.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "openthreads.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
{{- if .Values.metrics.annotations }}
prometheus.io/scrape: "true"
prometheus.io/port: "{{ .Values.service.port }}"
prometheus.io/path: "/api/metrics"
{{- end }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "openthreads.labels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "openthreads.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
envFrom:
- secretRef:
name: {{ if .Values.existingSecret }}{{ .Values.existingSecret }}{{ else }}{{ include "openthreads.fullname" . }}{{ end }}
env:
{{- range $key, $value := .Values.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
22 changes: 22 additions & 0 deletions deploy/helm/openthreads/templates/hpa.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "openthreads.fullname" . }}
labels:
{{- include "openthreads.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "openthreads.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
35 changes: 35 additions & 0 deletions deploy/helm/openthreads/templates/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "openthreads.fullname" . }}
labels:
{{- include "openthreads.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- toYaml .Values.ingress.tls | nindent 4 }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "openthreads.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}
Loading